我需要根据给定命名空间中的属性创建XPath表达式进行过滤。示例XML是:
<feed xmlns='http://www.w3.org/2005/Atom' xmlns:media='http://search.yahoo.com/mrss/'
xmlns:yt='http://gdata.youtube.com/schemas/2007'> ...
<entry>
<media:group>
<media:thumbnail url='http://i.ytimg.com/1.jpg' yt:name='default'/>
<media:thumbnail url='http://i.ytimg.com/2.jpg' yt:name='hqdefault'/>
<media:thumbnail url='http://i.ytimg.com/3.jpg' yt:name='start'/>
<media:thumbnail url='http://i.ytimg.com/4.jpg' yt:name='middle'/>
</media:group>
</entry>
我需要获取节点的url,其属性yt:name设置为'hqdefault'。
我尝试使用XPath表达式
'./media:group/media:thumbnail[@yt:name='hqdefault']/@url'
但似乎用yt:name指定namespaced属性不起作用。我在进行查询时得到一个空的DOMNodeList。
我在php中访问XML,所以我注册了yt namespace:
registerNamespace( 'yt', 'http://gdata.youtube.com/schemas/2007' );
Thnx提前
答案 0 :(得分:5)
XPath看起来是正确的。
可能是您的库不支持命名空间属性,或者您没有正确注册yt
命名空间和/或media
命名空间。
尝试匹配谓词过滤器内的local-name()
和namespace-uri()
,而不是使用名称空间前缀:
./*[local-name()='group'
and namespace-uri()='http://search.yahoo.com/mrss/'
]/*[local-name()='thumbnail'
and namespace-uri()='http://search.yahoo.com/mrss/'
and @*[local-name()='name'
and namespace-uri()='http://gdata.youtube.com/schemas/2007'
and .='hqdefault'
]
]/@url
如果这样可行,则在注册这些名称空间前缀的名称空间时会出现问题。
答案 1 :(得分:1)
假设其余部分正常,只需将xpath中的第一个.
替换为/
即可获取//media:group/...
(或以/atom:feed/media:group/...
开头并注册atom命名空间)
这是一个完整的工作示例:
<?php
$dom = new DOMDocument();
$dom->loadXML( <<<XML
<feed xmlns='http://www.w3.org/2005/Atom' xmlns:media='http://search.yahoo.com/mrss/'
xmlns:yt='http://gdata.youtube.com/schemas/2007'>
<entry>
<media:group>
<media:thumbnail url='http://i.ytimg.com/1.jpg' yt:name='default'/>
<media:thumbnail url='http://i.ytimg.com/2.jpg' yt:name='hqdefault'/>
<media:thumbnail url='http://i.ytimg.com/3.jpg' yt:name='start'/>
<media:thumbnail url='http://i.ytimg.com/4.jpg' yt:name='middle'/>
</media:group>
</entry>
</feed>
XML
);
$x = new DOMXPath( $dom );
$x->registerNamespace( 'yt', 'http://gdata.youtube.com/schemas/2007' );
$x->registerNamespace( 'media', 'http://search.yahoo.com/mrss/' );
$l= $x->query( "//media:group/media:thumbnail[@yt:name='hqdefault']/@url" );
for ($i=0; $i<$l->length; $i++) var_dump( $l->item($i)->value );
答案 2 :(得分:0)
yt
名称空间前缀用于示例XML,但未声明。如果那个示例XML确实存在,那么它就不是格式良好的XML(在命名空间术语中)。因此,没有通用的XML工具(如XSLT)可能能够处理它。
另一方面,如果源文档中某处有yt
名称空间前缀的声明,但您没有向我们展示过,那么您需要在XPath处理环境中声明(我猜是XSLT)相同名称空间URI的前缀。 E.g。
<xsl:stylesheet ... xmlns:yt="theNamespaceURIForYT">
XPath不知道源文档中出现的任何名称空间前缀声明。它只知道每个元素(和属性)属于哪个命名空间(URI)。