如何使用Nokogiri解析XML文件?

14

我在使用 Nokogiri 时遇到了一些问题。

我正在尝试解析这个 XML 文件:

<Collection version="2.0" id="74j5hc4je3b9">
  <Name>A Funfair in Bangkok</Name>
  <PermaLink>Funfair in Bangkok</PermaLink>
  <PermaLinkIsName>True</PermaLinkIsName>
  <Description>A small funfair near On Nut in Bangkok.</Description>
  <Date>2009-08-03T00:00:00</Date>
  <IsHidden>False</IsHidden>
  <Items>
    <Item filename="AGC_1998.jpg">
      <Title>Funfair in Bangkok</Title>
      <Caption>A small funfair near On Nut in Bangkok.</Caption>
      <Authors>Anthony Bouch</Authors>
      <Copyright>Copyright © Anthony Bouch</Copyright>
      <CreatedDate>2009-08-07T19:22:08</CreatedDate>
      <Keywords>
        <Keyword>Funfair</Keyword>
        <Keyword>Bangkok</Keyword>
        <Keyword>Thailand</Keyword>
      </Keywords>
      <ThumbnailSize width="133" height="200" />
      <PreviewSize width="532" height="800" />
      <OriginalSize width="2279" height="3425" />
    </Item>
    <Item filename="AGC_1164.jpg" iscover="True">
      <Title>Bumper Cars at a Funfair in Bangkok</Title>
      <Caption>Bumper cars at a small funfair near On Nut in Bangkok.</Caption>
      <Authors>Anthony Bouch</Authors>
      <Copyright>Copyright © Anthony Bouch</Copyright>
      <CreatedDate>2009-08-03T22:08:24</CreatedDate>
      <Keywords>
        <Keyword>Bumper Cars</Keyword>
        <Keyword>Funfair</Keyword>
        <Keyword>Bangkok</Keyword>
        <Keyword>Thailand</Keyword>
      </Keywords>
      <ThumbnailSize width="200" height="133" />
      <PreviewSize width="800" height="532" />
      <OriginalSize width="3725" height="2479" />
    </Item>
  </Items>
</Collection>

我希望所有的信息都能显示在屏幕上,就是这样。 应该很简单吧? 我正在做这个:

require 'nokogiri'

doc = Nokogiri::XML(File.open("sample.xml"))
@block = doc.css("items item").map {|node| node.children.text}
puts @block

每个Items都是一个节点,它下面有Item的子节点?

我创建了一个返回哈希的映射表,代码中的{}遍历每个节点并将子节点文本放入@block中。 然后我可以将所有子节点的文本显示到屏幕上。

我不知道我离目标有多远或接近,因为我已经阅读了很多文章,对基本概念仍然感到有些困惑,特别是当我使用一种新语言时,通常会从文件读取并输出到屏幕以进行基本程序。


如果你有任何特定的问题,请告诉我。我会回答你。 - Arup Rakshit
我有另一个问题。关于如何遍历节点树。 - camdixon
链接的问题指向此帖子。 - Arup Rakshit
1
请查看这个SAX解析选项,http://amolnpujari.wordpress.com/2012/03/31/reading_huge_xml-rb/ 新的OX Ruby解析器似乎比Nokogiri快5倍,https://gist.github.com/amolpujari/5966431 - Amol Pujari
2个回答

31

在这里,我将尝试为您解答所有的问题和疑惑:

require 'nokogiri'

doc = Nokogiri::XML.parse <<-XML
<Collection version="2.0" id="74j5hc4je3b9">
  <Name>A Funfair in Bangkok</Name>
  <PermaLink>Funfair in Bangkok</PermaLink>
  <PermaLinkIsName>True</PermaLinkIsName>
  <Description>A small funfair near On Nut in Bangkok.</Description>
  <Date>2009-08-03T00:00:00</Date>
  <IsHidden>False</IsHidden>
  <Items>
    <Item filename="AGC_1998.jpg">
      <Title>Funfair in Bangkok</Title>
      <Caption>A small funfair near On Nut in Bangkok.</Caption>
      <Authors>Anthony Bouch</Authors>
      <Copyright>Copyright © Anthony Bouch</Copyright>
      <CreatedDate>2009-08-07T19:22:08</CreatedDate>
      <Keywords>
        <Keyword>Funfair</Keyword>
        <Keyword>Bangkok</Keyword>
        <Keyword>Thailand</Keyword>
      </Keywords>
      <ThumbnailSize width="133" height="200" />
      <PreviewSize width="532" height="800" />
      <OriginalSize width="2279" height="3425" />
    </Item>
    <Item filename="AGC_1164.jpg" iscover="True">
      <Title>Bumper Cars at a Funfair in Bangkok</Title>
      <Caption>Bumper cars at a small funfair near On Nut in Bangkok.</Caption>
      <Authors>Anthony Bouch</Authors>
      <Copyright>Copyright © Anthony Bouch</Copyright>
      <CreatedDate>2009-08-03T22:08:24</CreatedDate>
      <Keywords>
        <Keyword>Bumper Cars</Keyword>
        <Keyword>Funfair</Keyword>
        <Keyword>Bangkok</Keyword>
        <Keyword>Thailand</Keyword>
      </Keywords>
      <ThumbnailSize width="200" height="133" />
      <PreviewSize width="800" height="532" />
      <OriginalSize width="3725" height="2479" />
    </Item>
  </Items>
</Collection>
XML
据我了解,Nokogiri中的每个“Items”都是一个节点,而在其下面有“Item”的子节点吗?
不是的,每个Items都是Nokogiri::XML::NodeSet对象。在此之下有两个Items的子节点,它们是Nokogiri::XML::Element类对象,你也可以称它们为Nokogiri::XML::Node
doc.class # => Nokogiri::XML::Document
@block = doc.xpath("//Items/Item")
@block.class # => Nokogiri::XML::NodeSet
@block.count # => 2
@block.map { |node| node.name }
# => ["Item", "Item"]
@block.map { |node| node.class }
# => [Nokogiri::XML::Element, Nokogiri::XML::Element]
@block.map { |node| node.children.count }
# => [19, 19]
@block.map { |node| node.class.superclass }
# => [Nokogiri::XML::Node, Nokogiri::XML::Node]

我们创建了一个映射表,它会返回一个哈希值。代码中的 {} 部分遍历每个节点并将子节点的文本放入 @block 中。然后我可以将所有这些子节点的文本显示在屏幕上。
我不理解这个。虽然我试着在下面解释什么是“节点”和“Nodeset”,但请记住,“Nodeset”是“Node”的集合。
@chld_class = @block.map do |node|
  node.children.class
end
@chld_class
# => [Nokogiri::XML::NodeSet, Nokogiri::XML::NodeSet]
@chld_name = @block.map do |node|
  node.children.map { |n| [n.name,n.class] }
end
@chld_name
# => [[["text", Nokogiri::XML::Text],
#      ["Title", Nokogiri::XML::Element],
#      ["text", Nokogiri::XML::Text],
#      ["Caption", Nokogiri::XML::Element],
#      ["text", Nokogiri::XML::Text],
#      ["Authors", Nokogiri::XML::Element],
#      ["text", Nokogiri::XML::Text],
#      ["Copyright", Nokogiri::XML::Element],
#      ["text", Nokogiri::XML::Text],
#      ["CreatedDate", Nokogiri::XML::Element],
#      ["text", Nokogiri::XML::Text],
#      ["Keywords", Nokogiri::XML::Element],
#      ["text", Nokogiri::XML::Text],
#      ["ThumbnailSize", Nokogiri::XML::Element],
#      ["text", Nokogiri::XML::Text],
#      ["PreviewSize", Nokogiri::XML::Element],
#      ["text", Nokogiri::XML::Text],
#      ["OriginalSize", Nokogiri::XML::Element],
#      ["text", Nokogiri::XML::Text]],
#     [["text", Nokogiri::XML::Text],
#      ["Title", Nokogiri::XML::Element],
#      ["text", Nokogiri::XML::Text],
#      ["Caption", Nokogiri::XML::Element],
#      ["text", Nokogiri::XML::Text],
#      ["Authors", Nokogiri::XML::Element],
#      ["text", Nokogiri::XML::Text],
#      ["Copyright", Nokogiri::XML::Element],
#      ["text", Nokogiri::XML::Text],
#      ["CreatedDate", Nokogiri::XML::Element],
#      ["text", Nokogiri::XML::Text],
#      ["Keywords", Nokogiri::XML::Element],
#      ["text", Nokogiri::XML::Text],
#      ["ThumbnailSize", Nokogiri::XML::Element],
#      ["text", Nokogiri::XML::Text],
#      ["PreviewSize", Nokogiri::XML::Element],
#      ["text", Nokogiri::XML::Text],
#      ["OriginalSize", Nokogiri::XML::Element],
#      ["text", Nokogiri::XML::Text]]]

@chld_name = @block.map do |node|
  node.children.map{|n| [n.name,n.text.strip] if n.elem? }.compact
end.compact
@chld_name
# => [[["Title", "Funfair in Bangkok"],
#      ["Caption", "A small funfair near On Nut in Bangkok."],
#      ["Authors", "Anthony Bouch"],
#      ["Copyright", "Copyright © Anthony Bouch"],
#      ["CreatedDate", "2009-08-07T19:22:08"],
#      ["Keywords", "Funfair\n        Bangkok\n        Thailand"],
#      ["ThumbnailSize", ""],
#      ["PreviewSize", ""],
#      ["OriginalSize", ""]],
#     [["Title", "Bumper Cars at a Funfair in Bangkok"],
#      ["Caption", "Bumper cars at a small funfair near On Nut in Bangkok."],
#      ["Authors", "Anthony Bouch"],
#      ["Copyright", "Copyright © Anthony Bouch"],
#      ["CreatedDate", "2009-08-03T22:08:24"],
#      ["Keywords",
#       "Bumper Cars\n        Funfair\n        Bangkok\n        Thailand"],
#      ["ThumbnailSize", ""],
#      ["PreviewSize", ""],
#      ["OriginalSize", ""]]]

@LuizDamimn 谢谢你! - Arup Rakshit

7

样本XML中的节点是大写的,因此您的代码应该反映出这一点。例如:

require 'nokogiri'

doc = Nokogiri::XML(File.open("sample.xml"))
@block = doc.css("Items Item").map { |node| node.children.text }
puts @block

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接