【问题标题】:PHP : how to parse XML with nested xpath elementsPHP:如何使用嵌套的 xpath 元素解析 XML
【发布时间】:2013-01-21 17:35:57
【问题描述】:

这是我正在处理的 XML:

<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:noo="http://www.myscheme.com/schema">
    <channel>
        <item>
            <title>A Simple Title</title>
            <noo:subcategory>the sub category</noo:subcategory>
            <noo:relatedInfos>
                <noo:teams>
                    <noo:team id="3">New York</noo:team>
                    <noo:team id="4">Las Vegas</noo:team>
                </noo:teams>
            </noo:relatedInfos>
        </item>
    </channel>
</rss>

我正在做这个php代码来获取两个“团队”但是它不起作用($xml有以前的内容):

$xml_datas = simplexml_load_string($xml);

foreach($xml_datas->channel->item as $item){                      
    $noo = $item->children('noo');
    echo $noo->team;
}

你知道它为什么不工作吗?

谢谢

【问题讨论】:

  • noo 不是该 xml 中的元素。这是namespace
  • @MarcB 我认为 Userco 意识到了这一点。 children() 将命名空间 URI 作为其参数,但这里的一个问题是 'noo' 是前缀,而不是命名空间 URI。

标签: php parsing xpath simplexml


【解决方案1】:

看看这是否有帮助:

<?php // RAY_temp_userco.php
error_reporting(E_ALL);

$xml = <<<ENDXML
<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:noo="http://www.myscheme.com/schema">
    <channel>
        <item>
            <title>A Simple Title</title>
            <noo:subcategory>the sub category</noo:subcategory>
            <noo:relatedInfos>
                <noo:teams>
                    <noo:team id="3">New York</noo:team>
                    <noo:team id="4">Las Vegas</noo:team>
                </noo:teams>
            </noo:relatedInfos>
        </item>
    </channel>
</rss>
ENDXML;

$obj = simplexml_load_string($xml);

$ns = $obj->getNamespaces(TRUE);

foreach($obj->channel->item as $item){
    $noo = $item->children($ns['noo']);
    var_dump($noo);
}

【讨论】:

  • 这里没有太多解释您在代码中所做的更改以及原因。此外,假设您使用的是 PHP >= 5.2,则无需在哈希中查找名称空间 URI,您可以使用 -&gt;children('noo', true)。当然,无论哪种方式,您都依赖于将来不会更改的别名。
  • 好的,我现在知道了。谢谢。
【解决方案2】:

"noo" 只是该命名空间的本地别名,-&gt;children() 方法(和大多数 XML 处理函数)想知道它的实际全局标识符,即 xmlns 属性中的 URI。

您需要指定命名空间的完整标识符(即-&gt;children('http://www.myscheme.com/schema'))或设置可选的第二个参数来告诉 SimpleXML 查找前缀(-&gt;children('noo', true)。第二个可能更具可读性,但它会中断如果未来的文档具有相同的架构,但给命名空间一个不同的本地别名。

另外,team 节点并不直接在item 节点下,所以需要进一步遍历才能得到它们:

// Give the namespace a readable name that won't change
define('NS_NOO', 'http://www.myscheme.com/schema');

$xml_datas = simplexml_load_string($xml);

foreach($xml_datas->channel->item as $item){                      
    $teams = $item->children(NS_NOO)->relatedInfo->teams;
    echo $teams->team[0];
}

【讨论】:

  • @Userco 您可以将其中一个答案标记为“已接受”,以便该问题在网站上显示为“已回答”。 :)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-09-28
  • 2015-03-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多