In questo capitolo vedremo quali strumenti Ruby mette a disposizione per la manipolazione dell'XML e approfondiremo YAML già visto nella prima parte di questa guida.
Cominciamo con REXML, che è parte della libreria standard, e permette l'utilizzo sia delle API DOM sia di quelle SAX. Per approfondire il linguaggio XML è utile consultare XML.HTML.it.
Nel corso del capitolo utilizzeremo un file XML di esempio di nome cd.xml che contiene questi dati:
<negozio nome="CD House">
<genere nome="Stoner">
<cd asin="B00000JBDE">
<titolo>Frequencies From Planet Ten</titolo>
<autore>Orange Goblin</autore>
<anno>1997</anno>
</cd>
<cd asin="B000WM72FC">
<titolo>Witchcult Today</titolo>
<autore>Electric Wizard</autore>
<anno>2007</anno>
</cd>
</genere>
<genere nome="Colonne sonore">
<cd asin="B00005O6PA">
<titolo>Amelie</titolo>
<autore>Yann Tiersen</autore>
<anno>2001</anno>
</cd>
</genere>
</negozio>
Com'è nello stile di questa guida entriamo subito nel vivo dell'esempio. Sorvoliamo la creazione di codice XML, che è un'operazione tediosa, e vediamo come estrarre dei dati dal file XML in una struttura di tipo REXML::Document sulla quale poi operare per ricavare tutti gli elementi.
require 'REXML/document'
xmlfile = File.new("cd.xml")
doc = REXML::Document.new(xmlfile)
doc.root.each_element do |gen|
puts gen.attributes["nome"]
gen.each_element do |cd|
cd.each_element do |val|
puts " #{val.name}: #{val.text}"
end
end
end
Dopo aver aperto il file XML e averlo passato a REXML::Document iniziamo a iterare sulla struttura partendo dall'elemento radice (doc.root) utilizzando il metodo each_element della classe Element.
Ad ogni chiamata di each_element scendiamo di un livello nella gerarchia del nostro file XML, ovvero passiamo da <negozio> a <genere> e quindi a <cd> dove ci fermiamo per ricavare i nomi e i valori degli elementi. Il risultato è il seguente:
Stoner titolo: Frequencies From Planet Ten autore: Orange Goblin anno: 1997 titolo: Witchcult Today autore: Electric Wizard anno: 2007 Colonne sonore titolo: Amelie autore: Yann Tiersen anno: 2001
Oltre a each_element la libreria mette a disposizione numerosi metodi per navigare tra gli elementi, abbiamo ad esempio next_element, previous_element ed anche variazioni di each_element come each_element_with_attribute e each_element_with_text.
Esaminiamo ora un esempio che fa uso del linguaggio XPath per navigare attraverso gli elementi del nostro file XML.
require 'REXML/document'
xmlfile = File.new("cd.xml")
doc = REXML::Document.new(xmlfile)
REXML::XPath.each(doc, '//genere/cd') do |cd|
puts "#{cd.elements["titolo"].text} - #{cd.elements["autore"].text}"
end
Qui troviamo each, che itera su ogni elemento specificato. Oltre a questo abbiamo due metodi altrettanto interessanti: first che restituisce il primo elemento che verifica il percorso indicato e match che restituisce un array di tutti gli elementi che verificano il path di ricerca impostato.
Esempio di ricerca con match
REXML::XPath.match(doc, '//[@nome="Stoner"]')
Concludiamo con un esempio di parsing di tipo SAX2:
require 'REXML/parsers/sax2parser'
xmlfile = File.new("cd.xml")
doc = REXML::Parsers::SAX2Parser.new(xmlfile)
doc.listen(:characters, ["titolo"]) do |titolo|
puts titolo
end
doc.parse
Dopo aver importato il file nel giusto oggetto, creiamo attraverso il metodo listen un evento characters, come secondo argomento passiamo un array contenente i tag che ci interessa utilizzare all'interno del blocco. Oltre a "characters" gli altri possibili eventi dall'ovvio significato sono: :start_element, :end_element, :cdata, :start_prefix_mapping, :end_prefix_mapping, :processing_instruction, :doctype, :attlistdecl, :elementdecl, :entitydecl, :notationdecl, :xmldecl, :comment.
Se vuoi aggiornamenti su Development inserisci la tua email nel box qui sotto: