【问题标题】:How to get first level children for XML using Nokogiri如何使用 Nokogiri 获取 XML 的第一级子级
【发布时间】:2017-04-05 06:43:26
【问题描述】:

我正在尝试使用 Nokogiri 解析 POM 文件,并且想要获取第一级子节点。

我的 POM 文件如下所示:

<project xmlns="some.maven.link">
   <parent>
     <groupId>parent.jar</groupId>
     <artifactId>parent-jar</artifactId>  
   </parent>         
   <groupId>child.jar</groupId>
   <artifactId>child-jar</artifactId>
 </project>

我正在尝试获取 artifactId “child-jar”,但我使用的 XPath 可能不正确,它首先获取的是“parent.jar”。

这是我的 Ruby 代码:

@pom = Nokogiri::XML(File.open(file_path))
p @pom.xpath("/project/artifactId", project"=>"http://maven.apache.org/POM/4.0.0")[0].text

我可以访问第二个元素,但这只是一个 hack。

【问题讨论】:

  • 虽然我没有工具来测试您的 ruby​​ 代码,但您的 XPath 应该返回only 'child-jar' : xpatheval.apphb.com/DI8w0z8D1.
  • 问题是命名空间。它没有在选择器中被引用,所以 Nokogiri/libXML2 不知道去哪里找。

标签: ruby xml xpath nokogiri


【解决方案1】:

您的 XML 示例似乎不正确。简化它:

require 'nokogiri'

doc = Nokogiri::XML(<<EOT)
<project>
  <parent>
    <groupId>parent.jar</groupId>
    <artifactId>parent-jar</artifactId>  
  </parent>         
  <groupId>child.jar</groupId>
  <artifactId>child-jar</artifactId>
</project>
EOT

doc.at('project > artifactId').text # => "child-jar"

使用 XPath 我会使用:

doc.at('/project/artifactId').text # => "child-jar"

我建议了解searchxpathcss 和它们的at* 表兄弟之间的区别,它们都记录在“Searching a XML/HTML Document”和Node 文档中。

在上面的示例中,我删除了 XML 命名空间信息以简化操作。 XML 命名空间很有用,但也很烦人,在您的示例 XML 中,您通过不提供有效的 URL 来破坏它。修复示例:

<project xmlns="http://www.w3.org/1999/xhtml">

我可以使用:

namespaces = doc.collect_namespaces  # => {"xmlns"=>"http://www.w3.org/1999/xhtml"}
doc.at('project > artifactId', namespaces).text # => "child-jar"

或:

doc.at('xmlns|project > xmlns|artifactId').text # => "child-jar"

我更喜欢并推荐第一个,因为它更易读且噪音更小。 Nokogiri 在选择器中的 CSS 实现有助于简化大多数选择器。在文档中传入收集的名称空间可以简化搜索,无论您使用的是 CSS 还是 XPath。

这些也有效:

doc.at('/xmlns:project/xmlns:artifactId').text # => "child-jar"
doc.at('/foo:project/foo:artifactId', {'foo' => "http://www.w3.org/1999/xhtml"}).text # => "child-jar"

请注意,第二个使用重命名的命名空间,如果您要处理文档中多余的 xmlns 声明并需要区分它们,这将非常有用。

Nokogiri 的“Namespaces”教程很有帮助。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-03-23
    • 2022-07-02
    相关资源
    最近更新 更多