【问题标题】:PHP SimpleXML XPath contains() to find other elements referenced by this elementPHP SimpleXML XPath contains() 查找此元素引用的其他元素
【发布时间】:2010-12-16 06:47:18
【问题描述】:

我得到了以下格式的 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,用于非常相似的目的,没有任何问题。

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


编辑: 为了完整性,并回答多个人的问题: 以下代码在代码的其他地方有效(尽管考虑到“22”与“2”的可能匹配,但并非 100% 正确。

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

【问题讨论】:

  • 我很困惑 元素上的 xpath 如何完全返回 '//passenger' 的任何结果,因为在您的示例 xml 结构中,单元不包含乘客。你能发布 $accomodation 对象是如何定义的吗?
  • 看来是SimpleXML对象的一个​​内置特性,Unit元素是直接创建一个包含整棵树的SimpleXML对象。
  • 有趣的功能 - 很高兴知道这一点,谢谢!
  • @jezmck:不,不是这样。请参阅下面的评论。 ;-)

标签: php xml xpath simplexml contains


【解决方案1】:

这个:

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

is:查找任何&lt;Passenger&gt; 与子&lt;PaxNo&gt;,其值包含子&lt;PaxAssociated&gt; 的值。它只适用于这样的数据结构(你显然没有):

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

【讨论】:

  • 最后一个代码 sn-p 有一个小错字,应该是contains('|(最后两个字符的倒置)
  • 同样的问题:'//passenger...' 的 xpath 在 $unit 对象上运行时如何返回任何内容(除非 $unit 对应于 来自标记)?
  • $Unit 已被直接定义为包含整个树的变量的子子元素。
  • @Henrik Opel:我怀疑您将'//''.//' 混淆了。前者 always 从根节点开始,与上下文无关。后者将上下文考虑在内。
  • @Henrik Opel:它不包含整个树,但它仍然可以引用它 - 毕竟它仍然是 DOM 的一部分。对于使用 // 的 XPath 查询,您当前在 DOM 中的哪个位置没有区别。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-07-09
  • 2021-03-21
  • 1970-01-01
  • 2020-05-02
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多