PHP simpleXMLelment xpath returns 意外的结果

PHP simpleXMLelment xpath returns unexpected results

我在问题底部的示例 XML 上执行了以下代码,但得到了意想不到的结果。

$xml = simplexml_load_string($xml_string);
$addresses = $xml->response->addressinformation;
var_dump($addresses->xpath('//record'));

我希望这只 return 两个 record 节点是当前 addresses 节点的子节点。但是,它实际上是 return 原始 $xml 元素的所有 5 个 record 节点。我读过的所有内容都说 // 符号是相对于当前节点的。我意识到还有其他方法可以获取我在问题中引用的两条记录。 $addresses->xpath('records/record'); 只是一个例子。但是,奇怪的行为是我遇到的一个更大问题的一部分,我只需要了解它为什么会这样。我读过的所有内容都会让我相信并非如此。谁能帮我理解一下?

样本XML

$xml_string = '
<?xml version="1.0" encoding="utf-8"?>
<root>
    <response>
        <addressinformation>
            <records>
                <record id="1">
                    <fullname>JOHN E DOE</fullname>
                    <firstname>JOHN</firstname>
                    <middlename>E</middlename>
                    <lastname>DOE</lastname>
                    <fulldob>01/01/1970</fulldob>
                </record>
                <record id="2">
                    <fullname>JOHN E DOE</fullname>
                    <firstname>JOHN</firstname>
                </record>
            </records>
        </addressinformation>
        <otherinformation>
            <records>
                <record id="3">
                    <fullname>JOHN DOE</fullname>
                    <firstname>JOHN</firstname>
                    <lastname>DOE</lastname>
                    <fulldob>01/01/1970</fulldob>
                </record>
                <record id="4">
                    <fullname>JOHN EDWARD DOE</fullname>
                    <firstname>JOHN</firstname>
                    <middlename>EDWARD</middlename>
                    <lastname>DOE</lastname>
                    <fulldob>19700000</fulldob>
                </record>
                <record id="5">
                    <fullname>JOHN EDWARD DOE</fullname>
                    <firstname>JOHN</firstname>
                    <middlename>EDWARD</middlename>
                    <lastname>DOE</lastname>
                    <fulldob>19830000</fulldob>
                </record>
            </records>
        </otherinformation>
    </response>
</root>
';

根据https://www.w3.org/TR/1999/REC-xpath-19991116/

//para selects all the para descendants of the document root and thus selects all para elements in the same document as the context node

.//para selects the para element descendants of the context node

注意后一个之前的点。这也适用于您的情况:

var_dump($addresses->xpath('.//record'));

正确地只显示了您期望的两个节点。

事情是 - 显然 - 即使所有对象都只是类型 SimpleXMLElement,您通过调用 simplexml_load_string() 创建的第一个对象出于某种原因被认为是文档根。当您将文档“分解”为节点和子节点时,这一切对我来说都很有意义。

但是 我同意这至少是 PHP 文档中未记录的某些行为,因此我建议您在那里提出编辑建议。