Php simplexml xpath contient () pour trouver d'autres éléments référencés par cet élément

StackOverflow https://stackoverflow.com/questions/1728947

Question

On me donne XML dans le format suivant, et je l'ai analysé avec le simplexml de PHP.

<?xml version="1.0" encoding="UTF-8"?>
<ManageMyBooking>
    <BookingInfo>
        <PartyDetails>
            <Passenger>
                <PaxNo>1</PaxNo>
                <Title>Mrs</Title>
                <Surname>Murphy</Surname>
            </Passenger>
            <Passenger>
                <PaxNo>2</PaxNo>
                <Title>Mr</Title>
                <Surname>Murphy</Surname>
            </Passenger>
            <Passenger>
                <PaxNo>3</PaxNo>
                <Title>Miss</Title>
                <Surname>Murphy</Surname>
            </Passenger>
        </PartyDetails>
        <Accommodation>
            <Units>
                <Unit>
                    <UnitNo>1</UnitNo>
                    <UnitDesc>...</UnitDesc>
                    <PaxAssociated>1|2</PaxAssociated>
                </Unit>
                <Unit>
                    <UnitNo>2</UnitNo>
                    <UnitDesc>...</UnitDesc>
                    <PaxAssociated>3</PaxAssociated>
                </Unit>
            </Units>
        </Accommodation>
    </BookingInfo>
</ManageMyBooking>

Je traverse les unités (chambres) ainsi:

// $Accommodation is a SimpleXML Object defined earlier, and able to provide relevant info
<?  foreach ($Accommodation->Units as $Units) {
        foreach ($Units->Unit as $Unit) {
        // (room/unit details echoed out here)
            foreach ($Unit->xpath('//Passenger[contains(PaxAssociated,./PaxNo)]') as $RoomPax) { ?>
<?= $RoomPax->Title $RoomPax->Surname" ?><br />
<?= "$RoomPax->Title $RoomPax->Surname" ?><br />
<?          }
        }
    } ?>

Dans une tentative de montrer les noms des passagers (PAX) dans chaque pièce.

Mais Ce XPath ne trouve personne, et ce qui suit obtient tout le monde.

//Passenger[contains(PaxNo,./PaxAssociated)]

Ce qui est particulièrement frustrant, c'est que j'ai utilisé avec succès XPath ailleurs dans le même PHP dans un but très similaire, sans problème.

Toute aide / conseils / suggestions sera très appréciée.


EDIT: Pour l'exhaustivité, et pour répondre à une question de plusieurs personnes: ce qui suit fonctionne ailleurs dans le code (mais pas à 100% correctement compte tenu de la correspondance possible sur «22» vs «2».

//Flight[contains(PaxAssociated,./PaxNo)]
Était-ce utile?

La solution

Cette:

//Passenger[contains(PaxNo,./PaxAssociated)]

est: trouvez n'importe quel <Passenger> avec un enfant <PaxNo> qui la valeur contient la valeur de l'enfant <PaxAssociated>. Cela ne fonctionnerait qu'avec une telle structure de données (que vous n'avez clairement pas):

<ManageMyBooking>
  <BookingInfo>
    <PartyDetails>
      <Passenger>
        <PaxNo>1|2</PaxNo>  <!-- note the exchanged value! -->
        <PaxAssociated>1</PaxAssociated>
      </Passenger>
    </PartyDetails>
  </BookingInfo>
</ManageMyBooking>

C'est donc mal sur plusieurs comptes. Ce que vous moyenne est probablement une expression dynamique de XPath, comme ceci:

foreach ($Units->Unit as $Unit) {
  $XPath = "//Passenger[contains('". $Unit->PaxAssociated . "', PaxNo)]";
  foreach ($Unit->xpath($XPath) as $RoomPax) {
    // ...
  }
}

Cela fonctionne au premier coup d'œil, mais il n'est pas sûr de l'échec, car "22" contient également "2". Donc faire un contains() seul ne t'a pas partout. Correct serait:

$XPath = "//Passenger[contains('|". $Unit->PaxAssociated ."|', concat('|', PaxNo, '|'))]";

De cette façon, vous vérifiez "| 22 |" contre "| 2 |", qui reviendrait faux.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top