循环遍历每个xml节点

时间:2014-06-23 10:06:54

标签: ruby xml xpath nokogiri

我希望这不是一个重复的问题。我花了很多时间寻找一个有效的解决方案,但我没有运气。我正在尝试做的是遍历每个xml节点并获取特定节点。为了达到这个目的,我使用的是Ruby,Nikogiri和xpath。

所以我有一个简单的xml文件,看起来像这个sitemap.xml:

<?xml version="1.0" encoding="UTF-8"?>
<url>
  <loc>http://www.stackoverflow.com/questions/ask1/</loc>
</url>
<url>
  <loc>http://www.stackoverflow.com/questions/ask2/</loc>
</url>
<url>
  <loc>http://www.stackoverflow.com/questions/ask3/</loc>
</url>

所以我试图提取每一个。这是我的代码:

siteMap = 'sitemap.xml'
sm = File.open(siteMap)
docSM = Nokogiri::XML(sm)

siteMapLinks = docSM.xpath("/url/loc").inner_text
print siteMapLinks.to_s + "\n"

输出&gt;

http://www.stackoverflow.com/questions/ask1/

因此您可以看到它不会输出所有节点/标记。我已经尝试将代码放在for循环中,但它所做的只是重复相同的节点。知道如何获得我想要的输出:

所需的输出&gt;

http://www.stackoverflow.com/questions/ask1/
http://www.stackoverflow.com/questions/ask2/
http://www.stackoverflow.com/questions/ask3/

3 个答案:

答案 0 :(得分:2)

您的文件不是有效的XML文档,因为it contains more than one root node。如果您inspect docSM变量的内容,您应该能够看到Nokogiri只解析了第一个<url>,因为它是第一个根节点。

您需要包含更高级别节点中的所有<url>以创建有效文档。即

<urls>
  <url>...</url>
  <url>...</url>
</urls>

答案 1 :(得分:2)

这很接近,但错过了一些小细节。 Nokogiri解析您的XML,直到关闭第一个顶级标记,因此如果您希望它解析所有URL,您将需要一些封装标记,如

<?xml version="1.0" encoding="UTF-8"?>
<urls>
  <url>
    <loc>http://www.stackoverflow.com/questions/ask1/</loc>
  </url>
  <url>
    <loc>http://www.stackoverflow.com/questions/ask2/</loc>
  </url>
  <url>
    <loc>http://www.stackoverflow.com/questions/ask3/</loc>
  </url>
</urls>

现在您可以使用

查询文档
docSM.xpath("//url/loc").each do |node|
  puts node.inner_text
end

如果你这样做

docSM.xpath("//url/loc").inner_text

正如您所建议的那样,您将获得一个字符串,其中所有文本都已连接在一起,并且两者之间没有分隔符。

答案 2 :(得分:2)

您的XML无效。您可以通过查看文档的errors方法来测试它:

require 'nokogiri'

doc = Nokogiri::XML(<<EOT)
<url>
  <loc>http://www.stackoverflow.com/questions/ask1/</loc>
</url>
<url>
  <loc>http://www.stackoverflow.com/questions/ask2/</loc>
</url>
EOT

doc.errors # => [#<Nokogiri::XML::SyntaxError: Extra content at the end of the document>]