Parsing XML with Ruby

Jestem nowy w pracy z XML, ale po prostu miałem potrzebę spadła mi na kolanach. Otrzymałem zwykły (dla mnie) format XML. W metkach są dwukropki.

<THING1:things type="Container">
  <PART1:Id type="Property">1234</PART1:Id>
  <PART1:Name type="Property">The Name</PART1:Name>
</THING1:things>

Jest to duży plik i jest w nim o wiele więcej niż to, ale mam nadzieję, że ten format będzie komuś znany. Czy ktoś wie jak podejść do tego typu dokumentów XML?

Wolałbym nie pisać brutalnego sposobu parsowania tekstu, ale nie mogę zrobić żadnych postępów z REXML lub Hpricot i podejrzewam, że to z powodu tych niezwykłych tagów.

Mój kod ruby:

    require 'hpricot'
    xml = File.open( "myfile.xml" )

    doc = Hpricot::XML( xml )

   (doc/:things).each do |thg|
     [ 'Id', 'Name' ].each do |el|
       puts "#{el}: #{thg.at(el).innerHTML}"
     end
   end

...który jest właśnie podnoszony z: http://railstips.org/blog/archives/2006/12/09/parsing-xml-with-hpricot/

I pomyślałem, że będę mógł coś wymyślić, ale ten kod nic nie zwraca. To nie błąd. Po prostu wraca.

Author: n8gard, 2012-06-25

2 answers

Jak wspomniał @pguardiario, Nokogiri jest de facto biblioteką parsowania XML i HTML. Jeśli chcesz wydrukować wartości Id i Name w swoim przykładzie, oto jak to zrobisz:

require 'nokogiri'

xml_str = <<EOF
<THING1:things type="Container">
  <PART1:Id type="Property">1234</PART1:Id>
  <PART1:Name type="Property">The Name</PART1:Name>
</THING1:things>
EOF

doc = Nokogiri::XML(xml_str)

thing = doc.at_xpath('//things')
puts "ID   = " + thing.at_xpath('//Id').content
puts "Name = " + thing.at_xpath('//Name').content

Kilka uwag:

  • at_xpath jest do dopasowania jednej rzeczy. Jeśli wiesz, że masz wiele elementów, zamiast tego chcesz użyć xpath.
  • w zależności od dokumentu przestrzenie nazw mogą być problematyczne, więc wywołanie doc.remove_namespaces! może pomóc (Zobacz ta odpowiedź dyskusja).
  • możesz użyć metod css zamiast xpath, Jeśli czujesz się z nimi lepiej.
  • zdecydowanie baw się tym w irb lub pry, aby zbadać metody.

Zasoby

Update

Aby obsłużyć wiele elementów, potrzebujesz elementu głównego i musisz usunąć // w xpath zapytanie.

require 'nokogiri'

xml_str = <<EOF
<root>
  <THING1:things type="Container">
    <PART1:Id type="Property">1234</PART1:Id>
    <PART1:Name type="Property">The Name1</PART1:Name>
  </THING1:things>
  <THING2:things type="Container">
    <PART2:Id type="Property">2234</PART2:Id>
    <PART2:Name type="Property">The Name2</PART2:Name>
  </THING2:things>
</root>
EOF

doc = Nokogiri::XML(xml_str)
doc.xpath('//things').each do |thing|
  puts "ID   = " + thing.at_xpath('Id').content
  puts "Name = " + thing.at_xpath('Name').content
end

To da Ci:

Id   = 1234
Name = The Name1

ID   = 2234
Name = The Name2

Jeśli jesteś bardziej zaznajomiony z selektorami CSS, możesz użyć tego prawie identycznego bitu kodu:

doc.css('things').each do |thing|
  puts "ID   = " + thing.at_css('Id').content
  puts "Name = " + thing.at_css('Name').content
end
 81
Author: jmdeldin,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-11-05 06:29:14

Jeśli w środowisku Rails, obiekt Hash jest rozszerzony i można skorzystać z metody from_xml:

xml = File.open("myfile.xml")
data = Hash.from_xml(xml)
 41
Author: IliasT,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-06-15 00:31:57