几天来我一直在尝试解决这个问题,但我似乎无法让它发挥作用。
假设我有一个名为 test.xml
的 XML 文件,如下所示:
<root>
<itemList>
<item>
<name>A</name>
<type>AAA</type>
</item>
<item>
<name>B</name>
<type>BBB</type>
</item>
<item>
<name>C</name>
<type>CCC</type>
</item>
</itemList>
</root>
在 PHP 中,我使用 SimpleXMLElement
查找包含文本 BBB
的节点。
<?php
$xmlStr = file_get_contents('test.xml');
$xml = new SimpleXMLElement($xmlStr);
$res = $xml->xpath('//type[contains(text(), "BBB")]/parent::*');
echo "{$res[0]->name} ({$res[0]->type})";
// Result: B (BBB)
现在,我想找到 parent
的 preceding-sibling
节点,并获取 child
节点的值,例如 A (AAA)
,但我根本不知道该怎么做。
任何帮助都会很棒。
谢谢。
最佳答案
要获取最近的前一个同级,请使用此 XPath 查询:
//type[contains(text(), "BBB")]/parent::item/preceding-sibling::item[1]
您需要将谓词设置为 1,以便选择最近的 sibling 。否则,您将始终获得第一个同级(例如,如果删除 [1]
谓词,您将获得两个 BBB< 的
和 AAA
元素CCC
)
请注意,通配符不是必需的,因为您可能已经知道标签是什么。
$xml = "<root>
<itemList>
<item>
<name>A</name>
<type>AAA</type>
</item>
<item>
<name>B</name>
<type>BBB</type>
</item>
<item>
<name>C</name>
<type>CCC</type>
</item>
</itemList>
</root>";
$xml = new SimpleXMLElement($xml);
$res = $xml->xpath('//type[contains(text(), "BBB")]/parent::item/preceding-sibling::item[1]');
echo "{$res[0]->name} ({$res[0]->type})".PHP_EOL;
$res = $xml->xpath('//type[contains(text(), "CCC")]/parent::item/preceding-sibling::item[1]');
echo "{$res[0]->name} ({$res[0]->type})";
结果
A (AAA)
B (BBB)
为了进一步说明使用谓词的必要性,请看一下:
$xml = "<root>
<itemList>
<item>
<name>A</name>
<type>AAA</type>
</item>
<item>
<name>B</name>
<type>BBB</type>
</item>
<item>
<name>C</name>
<type>CCC</type>
</item>
<item>
<name>C</name>
<type>DDD</type>
</item>
</itemList>
</root>";
$xml = new SimpleXMLElement($xml);
$res = $xml->xpath('//type[contains(text(), "DDD")]/parent::item/preceding-sibling::item');
var_dump($res);
结果
array (size=3)
0 =>
object(SimpleXMLElement)[2]
public 'name' => string 'A' (length=1)
public 'type' => string 'AAA' (length=3)
1 =>
object(SimpleXMLElement)[3]
public 'name' => string 'B' (length=1)
public 'type' => string 'BBB' (length=3)
2 =>
object(SimpleXMLElement)[4]
public 'name' => string 'C' (length=1)
public 'type' => string 'CCC' (length=3)
看看,无论您在查询中选择哪个元素,最远的同级元素总是在列表中的第一个(而最近的在最后一个)?因此,要模拟使用谓词,您还可以通过选择数组中的最后一个元素来获取最接近的同级元素(请注意,没有 [1]
谓词):
$res = $xml->xpath('//type[contains(text(), "DDD")]/parent::item/preceding-sibling::item');
$total = count($res);
echo "{$res[$total - 1]->name} ({$res[$total - 1]->type})".PHP_EOL;
关于PHP/XPATH - 查找父级的前一个 sibling 并获取其子级,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49247433/