Nessun risultato. Prova con un altro termine.
Guide
Notizie
Software
Tutorial
  • Lezione 16 di 32
  • livello principiante
Indice lezioni

REXML

Una libreria fondamentale per lavorare con file XML
Una libreria fondamentale per lavorare con file XML
Link copiato negli appunti

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.

Ti consigliamo anche