2009-11-13 100 views
1

我以下面的格式给出XML,并使用PHP的SimpleXML解析它。企图炫耀在每个房间的乘客(人)的姓名PHP SimpleXML XPath包含()以查找此元素引用的其他元素

// $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 /> 
<?   } 
     } 
    } ?> 

<?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> 

我循环通过单位(室),因此。

但是这个xpath找不到任何人,下面会得到所有人。

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

什么特别令人沮丧的是,我已经成功地使用XPath的其他地方一样PHP的一个非常相似的目的,没有任何问题。

任何帮助/意见/建议将不胜感激。


编辑: 的完整性,并回答多的人一个问题:在代码中的其他地方 下面的作品,(虽然不是100%正确地给出VS“2”“22”的可能匹配。

//Flight[contains(PaxAssociated,./PaxNo)] 
+0

我很困惑一个元素上的xpath如何返回'//乘客'的任何结果,因为在您的示例x​​ml结构中,单元不包含乘客。你可以发布如何定义$ accomodation对象吗? – 2009-11-13 12:52:32

+0

它似乎是SimpleXML对象的内置功能,Unit元素直接创建了一个包含整个树的SimpleXML对象。 – jezmck 2009-11-13 13:40:51

+0

有趣的功能 - 很好的了解这一点,谢谢! – 2009-11-13 13:51:08

回答

3

此:

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

是:找到与孩子<PaxNo>谁的价值的任何<Passenger>包含孩子的价值<PaxAssociated>。它只会与这样的数据结构(你显然没有):

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

所以这是错误的多个帐户。你什么意思可能是一个动态的XPath表达式,如:

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

这部作品乍看之下,但它不是万无一失,因为“22”包含“2”为好。所以单独做一个不会让你任何地方。正确的将是:

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

这样你检查“| 22 |”反对“| 2 |”,这将返回false。

+1

最后一个代码片段中有一个小的错字,应该是'contains('|'(倒数最后两个字符) – 2009-11-13 13:08:23

+0

Whhops。当然,感谢您的注意。:-) – Tomalak 2009-11-13 13:09:54

+0

同样的问题在这里:在$ unit对象上运行时,'// passenger ...'的xpath怎么会返回任何东西(除非$ unit会*不*对应于标记中的)? – 2009-11-13 13:28:17