PHP SimpleXML XPath包含()以查找此元素引用的其他元素

时间:2009-11-13 12:31:42

标签: php xml xpath simplexml contains

我正在以下列格式获得XML,并使用PHP的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>

我循环通过单位(房间):

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

试图在每个房间里显示乘客(Pax)的名字。

此xpath找不到任何人,以下内容将获得所有人。

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

特别令人沮丧的是,我已经在同一个PHP的其他地方成功使用了XPath,但没有任何问题。

非常感谢任何帮助/建议/建议。


编辑: 为了完整性,并回答多个人的问题: 以下在代码中的其他地方工作(尽管不是100%正确地给出了'22'与'2'的可能匹配。

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

1 个答案:

答案 0 :(得分:3)

此:

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

是:查找包含子<Passenger>的任何<PaxNo>,其值包含子<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”。因此单独执行contains()不会让您任何地方。正确的是:

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

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