Nokogiri/Xpath名称空间查询
问题描述:
我正在尝试使用xpath提取dc:title
元素。我可以使用以下代码提取元数据。Nokogiri/Xpath名称空间查询
doc = <<END
<?xml version="1.0" encoding="UTF-8"?>
<package xmlns="http://www.idpf.org/2007/opf" version="2.0">
<metadata xmlns:dc="URI">
<dc:title>title text</dc:title>
</metadata>
</package>
END
doc = Nokogiri::XML(doc)
# Awesome this works!
puts '//xmlns:metadata'
puts doc.xpath('//xmlns:metadata')
# => <metadata xmlns:dc="URI"><dc:title>title text</dc:title></metadata>
正如你所看到的,上述内容看起来工作正常。不过,我似乎无法从此节点树中获取标题信息,但以下所有内容均失败。
puts doc.xpath('//xmlns:metadata/title')
# => nil
puts doc.xpath('//xmlns:metadata/dc:title')
# => ERROR: `evaluate': Undefined namespace prefix
puts doc.xpath('//xmlns:dc:title')
# => ERROR: 'evaluate': Invalid expression: //xmlns:dc:title
是否有人可以解释如何使用上述xml文档在xpath中使用名称空间。
答
解析时需要注册所有名称空间。 Nokogiri自动在根节点上注册名称空间。任何不在根节点上的名称空间都必须注册。这应该工作:
puts doc.xpath('//dc:title', 'dc' => "URI")
或者,您可以完全删除名称空间。只有在确定没有冲突节点名称的情况下才能执行此操作。
doc.remove_namespaces!
puts doc.xpath('//title')
答
有了正确注册前缀为opf
命名空间'http://www.idpf.org/2007/opf'
URI,并为dc
'URI'
,您需要:
/*/opf:metadata/dc:title
注意:xmlns
和xml
是保留的,不能绑定到任何其它的命名空间URI的前缀比内置的'http://www.w3.org/2000/xmlns/'
和'http://www.w3.org/XML/1998/namespace'
。
答
作为显式构造名称空间URI的散列的替代方法,您可以从定义它们的xml元素中检索名称空间定义。使用
你的例子:
# First grab the metadata node, because that's where "dc" is defined.
metadata = doc.at_xpath('//xmlns:metadata')
# Pass metadata's namespaces as the resolver.
metadata.at_xpath('dc:title', metadata.namespaces)
注意,第二个XPath可能也一直在:
doc.at_xpath('//dc:title', metadata.namespaces).to_s
但是,为什么从根本上搜索,当你有一个更近的祖先?此外,您应该将名称空间定义元素及其子项作为名称空间的“范围”。搜索一个有限的范围不那么容易混淆,并且避免了细微的错误。
似乎没有工作doc.xpath('/ */opf:元数据/ dc:标题')#=>“评估”:未定义的命名空间前缀“ – Jamie 2011-01-14 12:30:28
@Jamie:你真的读过答案吗?第一句话开始*“有正确注册的前缀”* ... – 2011-01-14 12:39:49