14. Documentverwerking XML
![]() |
We bekijken het volgende document 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>
We analyseren dit document om de volgende console-uitvoer te genereren:
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
We moeten weten hoe we het volgende kunnen herkennen:
- een starttag zoals <opleiding>;
- een eindtag zoals </docent>;
- een starttag met attributen zoals <personne sexe="F">;
- de inhoud van een tag zoals martin in <nom>martin</nom>.
Het programma dat een code XML analyseert, wordt een parser XML genoemd. Twee modules bieden ons de functionaliteit om een code XML te analyseren: xml.sax en xml.sax.handler.
De module [xml.sax] levert ons een parser XML via de instructie:
Deze parser analyseert de tekst XML stapsgewijs. Hij roept bij bepaalde gebeurtenissen methoden van de gebruiker aan:
- de methode startElement bij het begin van een tag;
- de methode endElement bij het einde van een tag;
- de methode characters bij de inhoud van een tag.
We moeten de parser aangeven welke klasse deze methoden implementeert:
We geven aan de methode setContentHandler van de parser een instantie van de klasse die de methoden startElement, endElement en characters implementeert. De gebruikte klasse is een afgeleide van de klasse xml.sax.handler.ContentHandler. De voorgaande methoden worden aangeroepen met de volgende parameters:
- name is de naam van de starttag. attributs is het woordenboek met de attributen van de tag. Voor de tag <personne sexe="M"> hebben we dus name="personne" en attributs={'sexe':'M'}
- name is de naam van de afsluitende tag. Voor de tag </etudiant> wordt dit dus name='etudiant'.
- data is de inhoud van de tag. Dus als de tag
dan is data='\r\n dupont\r\n '. Over het algemeen worden de spaties voor en na de gegevens verwijderd.
Nu dit is uitgelegd, kunnen we verdergaan met het script voor het analyseren van een document XML:
# -*- coding=utf-8 -*-
import xml.sax, xml.sax.handler,re
# beheerklasse XML
class XmlHandler(xml.sax.handler.ContentHandler):
# functie die wordt aangeroepen bij het tegenkomen van een starttag
def startElement(self,name,attributs):
global depth
# een reeks spaties (inspringing)
print " " * depth,
# attributen
precisions=""
for (attrib,valeur) in attributs.items():
precisions+="(%s,%s) " % (attrib,valeur)
# de naam van de tag en eventuele attributen worden weergegeven
if precisions :
print "(%s,%s)" % (name,precisions)
else :
print name
# een extra niveau in de boomstructuur
depth+=1
# is dit een gegevens-tag?
global balisesDonnees,baliseDeDonnees
if balisesDonnees.has_key(name.lower()):
baliseDeDonnees=1
# de functie die wordt aangeroepen wanneer een eindtag wordt aangetroffen
def endElement(self,name):
# einde van de tag
# inspringingsniveau
global depth
depth-=1
# een reeks spaties (inspringing)
print " " * depth,
# de naam van de tag
print "/%s" % (name)
# de functie voor het weergeven van gegevens
def characters(self,data):
# gegevens
global baliseDeDonnees
# is de huidige tag een gegevenstag?
if not baliseDeDonnees :
return
# inspringingsniveau
global depth
# een reeks spaties (inspringing)
print " " * depth,
# de gegevens worden weergegeven
match=re.match(r"^\s*(.*)\s*$",data)
if match:
print "[%s]" % (match.groups()[0])
# einde van de gegevens-tag
baliseDeDonnees=False
# ------------------------------------------- main
# het programma
# gegevens
file="data.xml" # het XML-bestand
depth=0 # inspringingsniveau = diepte in de boomstructuur
balisesDonnees={"nom":1,"prenom":1,"age":1,"section":1,"formation":1}
baliseDeDonnees=True # indien waar, geeft aan dat het om een gegevens-tag gaat
# er wordt een XML-tekstanalyseobject aangemaakt
xml_parser=xml.sax.make_parser()
# de tagmanager
xml_parser.setContentHandler(XmlHandler())
# verwerking van het XML-bestand
xml_parser.parse(file)
Opmerkingen:
- het script maakt gebruik van de functiebibliotheek van de modules xml.sax en xml.sax.handler (regel 3);
- regel 62: het geanalyseerde bestand XML;
- regel 68: de parser XML;
- regel 70: de handler voor de door de parser gegenereerde gebeurtenissen zal een instantie zijn van de klasse XmlHandler;
- regel 72: de analyse van het document XML wordt gestart;
- regel 6: de klasse die de methoden startElement, endElement en characters implementeert. Deze is afgeleid van de klasse xml.sax.handler.ContentHandler, die methoden implementeert die door de parser worden gebruikt;
- regel 9: de methode startElement;
- regel 30: de methode endElement;
- regel 41: de methode characters.
De resultaten zijn dezelfde als die aan het begin van deze paragraaf zijn weergegeven.
