Nokogiri / Xpath命名空间查询
我正在尝试使用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文档在xpath中使用名称空间。
parsing时所有的名字空间都需要注册。 Nokogiri自动在根节点上注册名称空间。 任何不在根节点上的名称空间,你必须自己注册。 这应该工作:
puts doc.xpath('//dc:title', 'dc' => "URI")
或者,您可以删除命名空间。 只有在确定没有冲突节点名称的情况下才能执行此操作。
doc.remove_namespaces! puts doc.xpath('//title')
使用正确的'http://www.idpf.org/2007/opf'
命名空间URI的前缀opf
和'URI'
dc
,需要:
/*/opf:metadata/dc:title
注意 : xmlns
和xml
是保留的前缀,除了内置的'http://www.w3.org/2000/xmlns/'
和'http://www.w3.org/XML/1998/namespace'
'http://www.w3.org/2000/xmlns/'
之外,它们不能绑定到任何其他名称空间URI '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
但是为什么当你有一个更亲近的祖先从根源search? 另外,您应该将名称空间定义元素加上它的子元素作为名称空间的“范围”。 search一个有限的范围是较less的混淆,并避免微妙的错误。