Nokogiri和XPath有帮助

Mat*_*rby 8 ruby xml xpath nokogiri

不可否认,我是Nokogiri的新手,我必须遗漏一些东西......

我只是试图从这个XML中打印作者> name节点:

<?xml version="1.0" encoding="UTF-8"?>
<entry xmlns:gd="http://schemas.google.com/g/2005" xmlns:docs="http://schemas.google.com/docs/2007" xmlns="http://www.w3.org/2005/Atom" gd:etag="">
  <category term="http://schemas.google.com/docs/2007#document" scheme="http://schemas.google.com/g/2005#kind"/>
  <author>
    <name>Matt</name>
    <email>Darby</email>
  </author>
  <title>Title</title>
</entry>
Run Code Online (Sandbox Code Playgroud)

我正在尝试使用它,但它什么都没打印.看似没有节点(甚至'*')什么都不返回.

  Nokogiri::XML(@xml_string).xpath("//author/name").each do |node|
    puts node
  end
Run Code Online (Sandbox Code Playgroud)

jas*_*sso 13

亚历杭德罗已经在他的评论(+1)中回答了这个问题,但我也加入了这个答案,因为他遗漏了Nokogiri代码.

使用带有XPath的Nokogiri选择某些命名空间中的元素

您尝试选择的元素位于默认命名空间中,在这种情况下似乎是http://www.w3.org/2005/Atom.注意元素的xmlns="属性entry.您的XPath表达式会匹配不在任何名称空间中的元素.这就是为什么你的代码没有名称空间的原因

您需要为XPath表达式定义名称空间上下文,并指出XPath步骤以匹配该名称空间中的元素.AFAIK使用Nokogiri应该有几种不同的方法来实现这一点,其中一种如下所示

xml.xpath("//a:author/a:name", {"a" => "http://www.w3.org/2005/Atom"})
Run Code Online (Sandbox Code Playgroud)

请注意,这里我们定义了一个名称空间到前缀的映射,并a在XPath表达式中使用了这个前缀().


Mat*_*rby 7

出于某种原因,使用remove_namespaces!使上面的位按预期工作.

xml = Nokogiri::XML(@xml_string)
xml.remove_namespaces!
xml.xpath("//author/name").each do |node|
  puts node.text
end

=> "Matt"
Run Code Online (Sandbox Code Playgroud)

  • 原因是所有元素都在`http:// schemas.google.com/docs/2007`命名空间URI下.你必须声明这个URI之间的绑定是一个前缀,比如说`atom`,然后XPath expresion应该是`/*/atom:author/atom:name` (2认同)