我正在尝试使用xpath提取dc:title
元素。我可以使用以下代码提取元数据。
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 doc在xpath中使用命名空间。
答案 0 :(得分:66)
解析时需要注册所有名称空间。 Nokogiri自动在根节点上注册名称空间。任何不在根节点上的命名空间,您必须自己注册。这应该有效:
puts doc.xpath('//dc:title', 'dc' => "URI")
或者,您可以完全删除命名空间。只有在您确定没有冲突的节点名称时才执行此操作。
doc.remove_namespaces!
puts doc.xpath('//title')
答案 1 :(得分:1)
使用opf
命名空间URI的正确注册前缀'http://www.idpf.org/2007/opf'
和dc
的{{1}},您需要:
'URI'
注意:/*/opf:metadata/dc:title
和xmlns
是保留的前缀,无法绑定到除内置xml
和{{}之外的任何其他命名空间URI 1}}。
答案 2 :(得分:0)
作为显式构造名称空间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
但是,当你有一个更接近的祖先时,为什么要从根搜索?此外,您应该将namespace-defined元素及其子元素视为命名空间的“范围”。搜索有限的范围不那么容易混淆,并避免微妙的错误。