为什么我不能使用此PHP Xpath表达式选择所需的节点?

时间:2010-02-23 03:51:02

标签: php xpath simplexml

使用PHP,SimpleXML和xpath()函数,我想从某一点开始选择一个子节点。 你能帮我么?我知道在这个特定情况下我可以使用以“//”开头的表达式,但我想学习选择子节点的正确方法。 感谢。

首次尝试 - 未定义的偏移量失败:0 错误

$navXmlObject = simplexml_load_file("main_navigation.xml");
$tmpObject = $navXmlObject->website->xpath('title[@lang="fr"]'); 
echo($tmpObject[0]["label"]);

第二次尝试,添加斜杠 - 也失败并出现相同的错误

$tmpObject = $navXmlObject->website->xpath('/title[@lang="fr"]'); 

XML文件

<?xml version="1.0" encoding="UTF-8"?>
<root>
    <website id="MainWeb">
        <title lang="fr" label="Mon site Web" />        
        <title lang="en" label="My web site" />     
        <menuNodes>

            <menuNode id="Home">
                <menuNodeData lang="fr" label="Accueil" url="/fr/accueil/" />
                <menuNodeData lang="en" label="Home" url="/en/home/" />
            </menuNode>

            <menuNode id="Prod">

                <menuNodeData lang="fr" label="Produits" url="/fr/produits/" />
                <menuNodeData lang="en" label="Products" url="/en/products/" />

                <menuNode id="Shoe">
                    <menuNodeData lang="fr" label="Chaussures" url="/fr/produits/chaussures/" />
                    <menuNodeData lang="en" label="Shoes" url="/en/products/shoes/" />
                </menuNode>

            </menuNode>

            <menuNode id="Biog">
                <menuNodeData lang="fr" label="Biographie du fondateur" url="/fr/biographie/" />
                <menuNodeData lang="en" label="Biography of founder" url="/en/biography/" />
            </menuNode>

        </menuNodes>
    </website>
</root>

4 个答案:

答案 0 :(得分:1)

我建议W3Schools有一个非常好的XPath tutorial

正如您在问题中提到的,如果您想在文档中的任何位置选择所有<title/>元素,则可以使用

//title

(您可以添加谓词,例如[@lang="fr"]

  • 在XPath中,//表示“任何地方”。
  • 如果您的XPath表达式以//开头,则意味着“文档中的任何位置。”
  • 如果它以单个/开头,则意味着“位于文档的根目录。”
  • 最后,如果它不以任何斜杠开头,则表示“在上下文节点下。”

如果您知道树的结构不会改变,<title/>元素的确切路径将是

/root/website[@id="MainWeb"]/title[@lang="fr"]

现在假设您计划重组树并可能将<website/>节点移动到其他节点下。您可以说,“让我们在任何地方寻找<website/>节点 ,然后找到应该是其子节点的<title/>节点”在XPath中将是

//website[@id="MainWeb"]/title[@lang="fr"]

最后,要知道您可以使用单个点“。”将上下文节点用作搜索的根目录。 例如,使用SimpleXML,您可以使用

<title/>下查找<website/> 任何地方
$navXmlObject->website->xpath('.//title')

答案 1 :(得分:1)

强烈建议您升级到最近的稳定版本并享受随之而来的所有改进。现在已经结束了,你的代码无法正常工作的原因正是因为这样一个旧版本的SimpleXML的行为并不像你期望的那样。

查询的上下文节点不是您期望的那样(例如,与saner,更高版本相比)。为了便于理解,在我看来,使用绝对XPath会更容易。

一些适用于PHP 5.0.5(以及当前版本)的示例是:

$xmlObject->xpath("/root/website/title[@lang='fr']")
$xmlObject->xpath("./website/title[@lang='fr']")
$xmlObject->xpath("//website/title[@lang='fr']")
$xmlObject->xpath("website/title[@lang='fr']")

要投入一个扳手,这里有一个愚蠢的例子(但在5.0.5中应该适合你):

$xmlObject->website->menuNodes->xpath("title[@lang='fr']")

答案 2 :(得分:0)

根据w3

  

节点名|选择命名节点的所有子节点

答案 3 :(得分:0)

解决!

升级到最新版本的PHP解决了这个问题! 我完全从我的系统中卸载了PHP和Apache,而是使用了统一服务器 - 一个可移植的PHP / Apache环境(http://uniformserver.com/

感谢大家的帮助。