« Übersicht Projekte

Python: SAX-Parser

../../_images/tassenbaum.jpg

Lernziel

Mit dem SAX-Parser können Sie alle Aufgaben lösen, die auch mit XSL möglich sind, und natürlich können Sie weitere Optionen der Python-Sprache nutzen. Die Beispiele in dieser Station sollen Ihnen den Weg zeigen.

Handlungsanweisungen

Aufgaben

  • Erstellen Sie mit Hilfe des SAX-Parsers aus der Beispiel-Datei messdaten.xml/mdkurz.xml eine Komma-separierte Liste.

  • Speichern Sie die Liste in einer Datei ab.

  • Lesen Sie die Datei anschließend in Excel, OpenOffice oder einem anderen Programm, welches den CSV-Import unterstützt, ein.

Dateien für die Verarbeitung mit Python:

  • aufgabe4.py

  • mdkurz.xml

  • messdaten.xml

  • pcliste.dtd

  • pcliste.xml

  • sax1.py

  • sax2.py

  • sax3.py

Download der Dateien zur Station

Verfügbare Module

Es stehen gleich ein halbes Dutzend Module in der Standard-Bibliothek zur Verfügung.

  • xml.dom

  • xml.dom.minidom

  • xml.dom.pulldom

  • xml.parsers.expat

  • xml.sax

  • xml.sax.handler

  • xml.sax.saxutils

  • xml.sax.xmlreader

  • xmllib

xml.sax

Um mit dem SAX-Parser arbeiten zu können, muß eine Klasse erstellt werden, die von xml.sax.handler.ContentHandler erbt.

Damit können dann 5 Ereignisse verarbeitet werden:

  • startDocument

  • endDocument

  • startElement

  • endElement

  • characters

Auf die Attribute eines Elementes kann über das attrs-Dicitionary zugegriffen werden.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
import xml.sax

def main():
    parser = xml.sax.parse(open("pcliste.xml","r"),
                           SampleHandler())

class SampleHandler(xml.sax.handler.ContentHandler):

    def __init__(self):
        xml.sax.handler.ContentHandler.__init__(self)

    def startDocument(self):
        print("Start - Root-Element")

    def endDocument(self):
        print("Ende - Root-Element")

    def startElement(self,name,attrs):
        print(f"Element/Start: '{name}'")
        for (k,v) in attrs.items():
            print(f"   Attribut: {k} = {v}")

    def endElement(self,name):
        print(f"Element/Ende: '{name}'")

    def characters(self, chars):
        print("Element/Inhalt : '{chars}'")

if __name__ == '__main__':
    main()

Liste aller Räume und Computer

Dieses Beispiel zeigt, wie sie die Anzahl aller Rechner in jedem Raum ermitteln:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
import xml.sax

 def main():
     parser = xml.sax.parse(open("pcliste.xml","r"),
                           SampleHandler())

 class SampleHandler(xml.sax.handler.ContentHandler):

     def __init__(self):
         xml.sax.handler.ContentHandler.__init__(self)
         self.sumPC=0
         self.anzPC=0

     def startDocument(self):
         pass

     def endDocument(self):
         print(f"Anzahl Rechner : { self.sumPC }  ")

     def startElement(self,name,attrs):
         if name =="raum":
             print("Raum: ", attrs['bezeichnung'])
         if name=="rechner":
             self.anzPC = self.anzPC + 1

     def endElement(self,name):
         if name=="raum":
             self.sumPC= self.sumPC + self.anzPC
             print(self.anzPC)
             self.anzPC=0

     def characters(self, chars):
         pass

 if __name__ == '__main__':
     main()

Zuordnung Element/Funktion

Möchten Sie jedem Element eine extra Funktion spendieren, können Sie die Zuordnung in einem Dictionary verwalten, hier mit der Liste aller Räume und Computer:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
 import xml.sax

 def main():
     parser = xml.sax.parse(open("pcliste.xml","r"),
                            DictionaryBasedHandler())

 class DictionaryBasedHandler(xml.sax.handler.ContentHandler):

     def printTagName(self,name,attrs):
         print(name)

     def __init__(self):
         xml.sax.handler.ContentHandler.__init__(self)
         self.start_callbacks = { 'raum': self.printTagName,
                                  'rechner': self.printTagName }

     def startElement(self,name,attrs):
         if name in self.start_callbacks:
             self.start_callbacks[name](name,attrs)

 if __name__ == '__main__':
     main()