I'm being given XML in the following format, and am parsing it with PHP's SimpleXML.
<?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>
I'm looping through the Units (Rooms) thus:
// $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 />
<? }
}
} ?>
in an attempt to show the names off the Passengers (Pax) in each room.
But this xpath finds no-one, and the following gets everyone.
//Passenger[contains(PaxNo,./PaxAssociated)]
What's especially frustrating is that I've successfully used XPath elsewhere in the same PHP for a very similar purpose, with no problems.
Any help/advice/suggestions will be much appreciated.
Edit: for completeness, and to answer a question from multiple people: The following works elsewhere in the code, (though not 100% correctly given t开发者_Go百科he possible matching on '22' vs '2'.
//Flight[contains(PaxAssociated,./PaxNo)]
This:
//Passenger[contains(PaxNo,./PaxAssociated)]
is: Find any <Passenger>
with a child <PaxNo>
who's value contains the value of the child <PaxAssociated>
. It would only work with such a data structure (which you clearly don't have):
<ManageMyBooking>
<BookingInfo>
<PartyDetails>
<Passenger>
<PaxNo>1|2</PaxNo> <!-- note the exchanged value! -->
<PaxAssociated>1</PaxAssociated>
</Passenger>
</PartyDetails>
</BookingInfo>
</ManageMyBooking>
So this is wrong on multiple accounts. What you mean is probably a dynamic XPath expression, like this:
foreach ($Units->Unit as $Unit) {
$XPath = "//Passenger[contains('". $Unit->PaxAssociated . "', PaxNo)]";
foreach ($Unit->xpath($XPath) as $RoomPax) {
// ...
}
}
This works on first glance, but it is not fail-safe, because "22" contains "2" as well. So doing a contains()
alone won't get you anywhere. Correct would be:
$XPath = "//Passenger[contains('|". $Unit->PaxAssociated ."|', concat('|', PaxNo, '|'))]";
This way you check "|22|" against "|2|", which would return false.
精彩评论