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.
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
zamiastxpath
, Jeśli czujesz się z nimi lepiej. - zdecydowanie baw się tym w
irb
lubpry
, 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
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)
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