要获取最近的前同级,请使用以下 XPath 查询:
//type[contains(text(), "BBB")]/parent::item/preceding-sibling::item[1]
您需要将谓词设置为 1 以便选择最近的兄弟姐妹。否则你总是会得到第一个兄弟(例如,如果你删除[1] 谓词,你会得到BBB 和CCC 的AAA 元素)
请注意,通配符不是必需的,因为您可能已经知道标签是什么。
$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})";
Demo
结果
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;
Demo