我正在尝试使用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
我可以访问第二个元素,但这只是一个黑客。
答案 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"
我建议您了解search
,xpath
,css
及其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;教程很有帮助。