PHP / XPATH - 查找PARENT的PRECEDING-SIBLING并获得它的'儿童

时间:2018-03-13 02:35:04

标签: php xml xpath

我一直在努力想象这一天,但我似乎无法让它发挥作用。

我们说我有一个名为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)

现在,我想找到preceding-sibling的{​​{1}}节点,并获取parent个节点&#39}。像child这样的值,但我无法弄清楚如何做到这一点。

任何帮助都会很棒。

感谢。

2 个答案:

答案 0 :(得分:2)

要获取最近的前一个兄弟,请使用此XPath查询:

//type[contains(text(), "BBB")]/parent::item/preceding-sibling::item[1]

您需要将谓词设置为1,以便选择最近的兄弟姐妹。否则,您将始终获得第一个兄弟(例如,如果您删除[1]谓词,则会获得AAABBB的{​​{1}}元素<) / p>

请注意,通配符不是必需的,因为您可能已经知道标记是什么。

CCC

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>
    </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})";

结果

$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]

Demo

答案 1 :(得分:1)

请参阅演示https://implode.io/q9OOSC

$xmlStr = <<<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;

$xml = new SimpleXMLElement($xmlStr);

$res = $xml->xpath('//type[contains(text(), "BBB")]/parent::*/preceding-sibling::*');

echo "{$res[0]->name} ({$res[0]->type})";