首页 > 解决方案 > PHP simpleXMLelment xpath 返回意外结果

问题描述

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

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

我希望这只会返回record当前节点的两个子addresses节点。但是,它实际上返回record了原始$xml元素的所有 5 个节点。我读过的所有内容都表明该//符号是相对于当前节点的。我意识到还有其他方法可以获取我在问题中引用的两条记录。$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>
';

标签: phpxmlxpathsimplexml

解决方案


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

//para选择文档根的所有 para 后代,因此选择同一文档中的所有 para 元素作为上下文节点

.//para选择上下文节点的 para 元素后代

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

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

仅正确显示您期望的两个节点。

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

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


推荐阅读