14. Elaborazione dei documenti XML
![]() |
Consideriamo il seguente documento XML:
<tribu>
<enseignant>
<personne sexe="M">
<nom>dupont</nom>
<prenom>jean</prenom>
<age>28</age>
ceci est un commentaire
</personne>
<section>27</section>
</enseignant>
<etudiant>
<personne sexe="F">
<nom>martin</nom>
<prenom>charline</prenom>
<age>22</age>
</personne>
<formation>dess IAIE</formation>
</etudiant>
</tribu>
Analizziamo questo documento per ottenere il seguente output della console:
tribu
enseignant
(personne,(sexe,M) )
nom
[dupont]
/nom
prenom
[jean]
/prenom
age
[28]
/age
/personne
section
[27]
/section
/enseignant
etudiant
(personne,(sexe,F) )
nom
[martin]
/nom
prenom
[charline]
/prenom
age
[22]
/age
/personne
formation
[dess IAIE]
/formation
/etudiant
/tribu
Dobbiamo sapere come riconoscere:
- un tag di apertura come <formazione>;
- un tag di chiusura come </insegnante>;
- un tag di apertura con attributi come <personne sexe="F">;
- il corpo di un tag come martin in <nom>martin</nom>.
Il programma che analizza un codice XML è chiamato parser XML. Due moduli ci forniscono le funzionalità per analizzare un codice XML: xml.sax e xml.sax.handler.
Il modulo [xml.sax] ci fornisce un parser XML tramite l'istruzione:
Questo parser analizza il testo XML in modo sequenziale. Richiama i metodi dell’utente in occasione di determinati eventi:
- il metodo startElement all'inizio di un tag;
- il metodo endElement alla fine di un tag;
- il metodo characters sul corpo di un tag.
Dobbiamo indicare al parser la classe che implementa questi metodi:
Passiamo al metodo setContentHandler del parser, un'istanza della classe che implementa i metodi startElement, endElement, characters. La classe utilizzata è una classe derivata dalla classe xml.sax.handler.ContentHandler. I metodi precedenti vengono chiamati con i seguenti parametri:
- name è il nome del tag di apertura. attributs è il dizionario degli attributi del tag. Pertanto, per il tag <personne sexe="M"> avremo name="personne" e attributs={'sexe':'M'}
- name è il nome del tag di chiusura. Pertanto, per il tag </etudiant> si avrà name='etudiant'.
- data è il corpo del tag. Quindi, se il tag è
si avrà data='\r\n dupont\r\n '. In generale, si eliminano gli spazi che precedono e seguono il dato.
Chiarito questo, si può passare allo script di analisi di un documento XML:
# -*- coding=utf-8 -*-
import xml.sax, xml.sax.handler,re
# classe di gestione XML
class XmlHandler(xml.sax.handler.ContentHandler):
# funzione chiamata all'incontro di un tag di inizio
def startElement(self,name,attributs):
global depth
# una sequenza di spazi (indentazione)
print " " * depth,
# attributi
precisions=""
for (attrib,valeur) in attributs.items():
precisions+="(%s,%s) " % (attrib,valeur)
# vengono visualizzati il nome del tag e gli eventuali attributi
if precisions :
print "(%s,%s)" % (name,precisions)
else :
print name
# un ulteriore livello della struttura ad albero
depth+=1
# si tratta di un tag di dati?
global balisesDonnees,baliseDeDonnees
if balisesDonnees.has_key(name.lower()):
baliseDeDonnees=1
# la funzione chiamata quando si incontra un tag di chiusura
def endElement(self,name):
# fine del tag
# livello di indentazione
global depth
depth-=1
# una sequenza di spazi (indentazione)
print " " * depth,
# il nome del tag
print "/%s" % (name)
# funzione di visualizzazione dei dati
def characters(self,data):
# dati
global baliseDeDonnees
# il tag corrente è un tag di dati?
if not baliseDeDonnees :
return
# livello di indentazione
global depth
# una sequenza di spazi (indentazione)
print " " * depth,
# i dati vengono visualizzati
match=re.match(r"^\s*(.*)\s*$",data)
if match:
print "[%s]" % (match.groups()[0])
# fine del tag dati
baliseDeDonnees=False
# ------------------------------------------- main
# il programma
# dati
file="data.xml" # il file xml
depth=0 # livello di indentazione = profondità nella struttura ad albero
balisesDonnees={"nom":1,"prenom":1,"age":1,"section":1,"formation":1}
baliseDeDonnees=True # se vero, indica che si tratta di un tag di dati
# si crea un oggetto di analisi del testo XML
xml_parser=xml.sax.make_parser()
# il gestore dei tag
xml_parser.setContentHandler(XmlHandler())
# elaborazione del file XML
xml_parser.parse(file)
Note:
- lo script utilizza la libreria di funzioni dei moduli xml.sax, xml.sax.handler (riga 3);
- riga 62: il file XML analizzato;
- riga 68: il parser XML;
- riga 70: il gestore degli eventi generati dal parser sarà un'istanza della classe XmlHandler;
- riga 72: viene avviata l'analisi del documento XML;
- riga 6: la classe che implementa i metodi startElement, endElement, characters. Essa deriva dalla classe xml.sax.handler.ContentHandler che implementa i metodi utilizzati dal parser;
- riga 9: il metodo startElement;
- riga 30: il metodo endElement;
- riga 41: il metodo characters.
I risultati sono quelli presentati all'inizio di questo paragrafo.
