2013-07-11 16 views
10

Mam pewne problemy z Nokogiri.Jak używać Nokogiri do parsowania pliku XML?

Próbuję analizować ten plik 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> 

chcę wszystkich tych informacji wyświetlanej na ekranie, to wszystko. Powinien być prosty, prawda? Robię to:

require 'nokogiri' 

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

Każdy Items jest węzłem, a pod które są dzieci węzły Item?

Tworzę mapę tego, która zwraca skrót, a kod w {} przechodzi przez każdy węzeł i umieszcza tekst podrzędny na @block. Następnie mogę wyświetlić cały tekst węzła podrzędnego na ekranie.

Nie mam pojęcia, jak daleko lub blisko jestem, ponieważ przeczytałem tak wiele artykułów, i wciąż jestem trochę zdezorientowany, zwłaszcza, że ​​zazwyczaj z nowym językiem, czytam z pliku i wyprowadzam do ekran podstawowego programu.

+0

Jeśli masz jakieś konkretne pytanie, powiedz mi. Odpowiem ci. –

+0

Mam kolejne pytanie. http: // stackoverflow.com/questions/17600037/using-nokogiri-to-parse-xml-file Chodzi o to, jak przemierzać drzewo węzłów. – camdixon

+0

powiązane pytania do tego posta. –

Odpowiedz

26

Tutaj postaram się wyjaśnić Ci wszystkie pytania/niejasności masz:

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 

Więc z mojego zrozumienia Nokogiri, każda „przedmioty” jest węzłem, a pod które są węzły dziecięce z "Przedmiotem"?

Nie, każdy przedmiotyNokogiri::XML::NodeSet. A pod nim są 2 węzły podrzędne z Przedmioty, które są z obiektu klasy Nokogiri::XML::Element. Można powiedzieć, że im także 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] 

Tworzymy mapę tego, która zwraca hash wierzę, a kod w {} przechodzi każdego węzła i umieszcza tekst dzieci do @block . Następnie mogę wyświetlić cały tekst tego węzła podrzędnego na ekranie.

Nie rozumiem tego. Chociaż próbowałem wyjaśnić poniżej, aby pokazać, co jest Węzeł, a co to jest Zestaw węzłów w Nokogiri. Pamiętaj, Nodeset jest zbiorem węzłów.

@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", ""]]] 
+0

Świetna odpowiedź! (y) –

+0

@ LuizDamimn Dzięki! –

4

węzłów XML próbki są kapitalizowane, więc kod powinien odzwierciedlać. Na przykład:

require 'nokogiri' 

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