14. Processing of document XML
![]() |
Consider the following XML document:
<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 parse this document to produce the following console output:
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 need to know how to recognize:
- a start tag such as <training>;
- an end tag such as </teacher>;
- a start tag with attributes such as <person gender="F">;
- the body of a tag such as martin in <name>martin</name>.
The program that analyzes a XML code is called a XML parser. Two modules provide the functionality to parse a XML code: xml.sax and xml.sax.handler.
The [xml.sax] module provides us with a XML parser using the following statement:
This parser parses the text XML sequentially. It calls user methods on events:
- the startElement method on a tag start;
- the endElement method on a tag end;
- the characters method on the body of a tag.
We need to tell the parser which class implements these methods:
We pass to the parser’s setContentHandler method an instance of a class that implements the startElement, endElement, and characters methods. The class used is a subclass of the xml.sax.handler.ContentHandler class. The preceding methods are called with parameters:
- name is the name of the start tag. attributes is the dictionary of the tag's attributes. Thus, for the tag <person sex="M">, we will have name="person" and attributes={'sex':'M'}
- name is the name of the closing tag. Thus, for the </student> tag, we will have name='student'.
- data is the body of the tag. Thus, if the tag is
we will have data='\r\n dupont\r\n '. Generally, we will remove the whitespace preceding and following the data.
With that explained, we can move on to the script for parsing a XML document:
# -*- coding=utf-8 -*-
import xml.sax, xml.sax.handler,re
# management class XML
class XmlHandler(xml.sax.handler.ContentHandler):
# function called when a start tag is encountered
def startElement(self,name,attributs):
global depth
# a sequence of spaces (indentation)
print " " * depth,
# attributes
precisions=""
for (attrib,valeur) in attributs.items():
precisions+="(%s,%s) " % (attrib,valeur)
# displays the tag name and any attributes
if precisions :
print "(%s,%s)" % (name,precisions)
else :
print name
# an extra level of tree structure
depth+=1
# is it a data tag?
global balisesDonnees,baliseDeDonnees
if balisesDonnees.has_key(name.lower()):
baliseDeDonnees=1
# the function called when an end tag is encountered
def endElement(self,name):
# end of tag
# indentation level
global depth
depth-=1
# a sequence of spaces (indentation)
print " " * depth,
# tag name
print "/%s" % (name)
# data display function
def characters(self,data):
# data
global baliseDeDonnees
# is the current tag a data tag?
if not baliseDeDonnees :
return
# indentation level
global depth
# a sequence of spaces (indentation)
print " " * depth,
# data are displayed
match=re.match(r"^\s*(.*)\s*$",data)
if match:
print "[%s]" % (match.groups()[0])
# end of data tag
baliseDeDonnees=False
# ------------------------------------------- main
# the program
# data
file="data.xml" # the xml file
depth=0 # indentation level=depth in tree structure
balisesDonnees={"nom":1,"prenom":1,"age":1,"section":1,"formation":1}
baliseDeDonnees=True # to true, indicates a data tag
# create a text analysis object xml
xml_parser=xml.sax.make_parser()
# the tag manager
xml_parser.setContentHandler(XmlHandler())
# use of the xml file
xml_parser.parse(file)
Notes:
- The script uses the function library from the modules xml.sax and xml.sax.handler (line 3);
- line 62: the parsed XML file;
- line 68: the XML parser;
- line 70: the handler for events emitted by the parser will be an instance of the XmlHandler class;
- line 72: the parsing of the XML document is initiated;
- line 6: the class implementing the methods startElement, endElement, and characters. It is derived from the class xml.sax.handler.ContentHandler, which implements methods used by the parser;
- line 9: the method startElement;
- line 30: the endElement method;
- line 41: the characters method.
The results are those presented at the beginning of this paragraph.
