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 

注意xmlnsxml是保留的前缀,除了内置的'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的混淆,并避免微妙的错误。