如何使用Nokogiri

时间:2017-03-30 01:12:11

标签: ruby xml xpath nokogiri

我正在尝试使用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

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

1 个答案:

答案 0 :(得分: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*堂兄弟之间的差异,这些差异都记录在&#34; {{ 3}}&#34;和Searching a XML/HTML Document文档。

在上面的示例中,我删除了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&#34; Node&#34;教程很有帮助。