Wiki-Bereiche:

Informationstechnik (IT)
Hobbys

Artikel in diesem Bereich:

Zum Ende der Metadaten springen
Zum Anfang der Metadaten springen
Dieses Dokument befindet sich noch im Aufbau. Der Abschnitt über die DOM-Parser ist noch unvollständig.

Grundlagen und Allgemeines

XML-Parser bieten über zwei verschiedene Schnittstellen Zugriff auf ein XML-Dokument: SAX oder DOM. SAX steht für "Simple API for XML" und ist ereignisorientiert ("event based"). Das bedeutet, dass der Parser das XML-Dokument sequenziell einliest und bei einem bestimmten XML-Konstrukt ein Ereignis auslöst (z.B. bei einem aufgehenden oder schließenden XML-Tag, einem Attribut oder bei Text). Im Gegensatz dazu, wird bei DOM ("Document Object Model") beim Parsen des XML-Dokuments ein Baum aufgebaut. Dieser sogenannte DOM-Tree ist das Abbild des XML-Dokuments und wird im Speicher vorgehalten.

Vor- und Nachteile zwischen SAX und DOM:

  • SAX: schnell, minimaler Speicherverbrauch, Parsen direkt beim Einlesen des XML-Dokuments möglich, umständlich beim Parsen von komplexen XML-Dokumenten
  • DOM: langsamer, hoher Speicherverbrauch, Zugriff erst nach kompletten Einlesen des XML-Dokuments möglich, einfacher Zugriff und Manipulation des XML-Dokuments über DOM-Tree

Alle hier aufgeführten Parser basieren auf der C-Bibliothek libxml2, die Bestandteil des IPhone SDKs ist und sowohl SAX als auch DOM unterstützt.

SAX-Parser

Apple CFoundation Class "NSXMLParser"

Bestandteil des IPhone SDKs ist die Objective-C Klasse NSXMLParser und implementiert mittels der C-Bibliothek libxml2 einen SAX-Parser. Der Parser durchläuft das XML-Dokument und ruft für bestimmte XML-Konstrukte verschiedene Methoden des delegierten Objekts auf. Im folgenden eine einfache Implementierung für das Parsen der Heise-Webseite:

Folgender HTML-Code von der Heise Webseite ...

... erzeugt diese Debug-Ausgabe im Beispielprogramm:

2009-05-03 15:18:53.797 ParserTest[14281:20b] startElement: li
2009-05-03 15:18:53.798 ParserTest[14281:20b] startElement: a
2009-05-03 15:18:53.798 ParserTest[14281:20b]  attrs: href = "http://www.heise.de/ct/Datenschuetzer-Das-Jahr-der-Skandale-nicht-der-Konsequenzen--/news/meldung/135491"
2009-05-03 15:18:53.799 ParserTest[14281:20b]  attrs: title = "Datenschützer: "Das Jahr der Skandale, nicht der Konsequenzen""
2009-05-03 15:18:53.799 ParserTest[14281:20b]  chars: "Das Jahr der Skandale, nicht der Konsequenzen"
2009-05-03 15:18:53.799 ParserTest[14281:20b] endElement: a
2009-05-03 15:18:53.801 ParserTest[14281:20b] endElement: li

Das Parsen von wohlgeformten XHTML-Code, wie auf der Heise-Webseite, funktioniert mit dem NSXMLParser einwandfrei. Bei nicht-XML-konformen, "unsauberen" HTML-Code treten jedoch Probleme auf. Folgender HTML-Code ...

... erzeugt diese Debug-Ausgabe:

2009-05-03 14:57:19.259 ParserTest[14155:20b] startElement: TABLE
2009-05-03 14:57:19.260 ParserTest[14155:20b]  attrs: CLASS = "infoBox"
2009-05-03 14:57:19.261 ParserTest[14155:20b]  chars: 1 CELLSPACING=0 CELLPADDING=0>
2009-05-03 14:57:19.263 ParserTest[14155:20b] startElement: TR
2009-05-03 14:57:19.263 ParserTest[14155:20b] startElement: TD
2009-05-03 14:57:19.271 ParserTest[14155:20b]  attrs: CLASS = "infoBox"
2009-05-03 14:57:19.271 ParserTest[14155:20b]  chars:
2009-05-03 14:57:19.272 ParserTest[14155:20b] startElement: DIV
2009-05-03 14:57:19.272 ParserTest[14155:20b]  attrs: CLASS = "infoBoxTitle"
2009-05-03 14:57:19.273 ParserTest[14155:20b]  chars: Current Status
2009-05-03 14:57:19.274 ParserTest[14155:20b] endElement: DIV

HTML-Attribute werden irrtümlich als Text (cellspacing=0, cellpadding=0) oder gar nicht erkannt (border=1). Teilweise führt HTML-Code sogar zu Speicherzugriffsfehlern (Absturz IPhone Applikation).

Zusätzlich kommt es bei sehr großen XML-Dokumenten zu einem erhöhten Speicherverbrauch, da das komplette Dokument dem libxml-Parser übergeben wird. Besser wäre eine inkrementelle Übergabe von Teilen des XML-Dokuments. So könnte zusätzlich auch ein XML-Dokument schon beim Einlesen (z.B. während des Downloads von einem Server) geparst und die gesamte Bearbeitungszeit verkürzt werden. Als letzte Herausforderung ist der "case-sensitiv" Zugriff auf die XML-Attribute über die NSDictionary-Objekte zu erwähnen. Es gibt "von Haus aus" keine Möglichkeit unabhängig von der Groß- und Kleinschreibung der NSDictonary-Keys (also der Namen der XML-Attribute) auf die Werte zuzugreifen. Eine ausführliche Diskussion hierzu ist bei Apple-List zu finden.

AQXMLParser

Die Objective-C Klasse AQXMLParser setzt auf den NSXMLParser auf und versucht die genannten Probleme zu lösen. Hierzu wird das XML-Dokument über ein NSInputStream-Objekt in 1kb großen Datenstücken an die libxml2-Methode "xmlParseChunk()" weitergereicht. Ein Vergleich zum Speicherverbrauch gegenüber NSXMLParser ist auf dem Blog des Entwicklers zu finden. Der Quellcode des Parser ist bei github veröffentlicht.

Zusätzlich bietet die Klasse einen HTML-Modus, mit dem auch nicht wohlgeformter HTML-Code einwandfrei geparst werden kann.

Der oben aufgeführte HTML-Code, der vom NSXMLParser nicht richtig geparst wurde, macht beim AQXMLParser im HTML-Modus kein Problem:

2009-05-03 16:12:38.536 ParserTest[17346:20b] startElement: table
2009-05-03 16:12:38.536 ParserTest[17346:20b]  attrs: cellpadding = "0"
2009-05-03 16:12:38.536 ParserTest[17346:20b]  attrs: class = "infoBox"
2009-05-03 16:12:38.537 ParserTest[17346:20b]  attrs: border = "1"
2009-05-03 16:12:38.538 ParserTest[17346:20b]  attrs: cellspacing = "0"
2009-05-03 16:12:38.538 ParserTest[17346:20b]  chars:
2009-05-03 16:12:38.539 ParserTest[17346:20b] startElement: tr
2009-05-03 16:12:38.540 ParserTest[17346:20b] startElement: td
2009-05-03 16:12:38.540 ParserTest[17346:20b]  attrs: class = "infoBox"
2009-05-03 16:12:38.541 ParserTest[17346:20b]  chars:
2009-05-03 16:12:38.541 ParserTest[17346:20b] startElement: div
2009-05-03 16:12:38.541 ParserTest[17346:20b]  attrs: class = "infoBoxTitle"
2009-05-03 16:12:38.542 ParserTest[17346:20b]  chars: Current Network Status
2009-05-03 16:12:38.542 ParserTest[17346:20b] endElement: div

Jedoch bricht der XML-Parser sofort bei sämtlichen Parser-Fehlern den kompletten Prozess ab:

2009-05-03 16:12:39.259 ParserTest[17346:20b] startElement: td
2009-05-03 16:12:39.261 ParserTest[17346:20b]  attrs: align = "left"
2009-05-03 16:12:39.264 ParserTest[17346:20b]  attrs: valign = "center"
2009-05-03 16:12:39.264 ParserTest[17346:20b]  attrs: class = "statusEven"
2009-05-03 16:12:39.265 ParserTest[17346:20b]  ==> ERROR: Operation could not be completed. (NSXMLParserErrorDomain error 23.) -> (null)
2009-05-03 16:12:39.265 ParserTest[17346:20b] startElement: a

Außerdem kommt es beim Kompilieren des Quellcodes beim "@property parserError" in der Header-Datei AQXMLPaser.h zu Syntax-Fehlern und beim Einlesen von NSData über die Methode "initWithData" zu Speicherzugriffsfehler. Folgender Patch behebt die Fehler und ergänzt eine neue Boolean-Variable abortOnErrors mit Setter- (setAbortOnErrors()) und Getter-Methode (abortOnErrors()), über die konfiguriert wird, ob bei XML Parser-Fehler das Parsen abgebrochen werden soll:

Aufruf der Klasse für das Parsen von HTML-Code:

Software:Patch für AQXMLParser:

XML-Parser-Beispiel "XMLPerformance" von Apple

Apple stellt auf der Developer-Seite eine Beispiel-Implementierung eines performanten XML-Parsers als Alternative zu NSXMLParser zur Verfügung:

DOM-Parser

Übersicht der DOM-Parser für das IPhone mit einigen Notizen:

SAX-/DOM-Parser

Kombination aus SAX und DOM-Parser in einer Objective-C Klasse:

Stichwörter

Geben Sie Stichwörter ein, die dieser Seite hinzugefügt werden sollen:
Please wait 
Sie suchen ein Stichwort? Beginnen Sie einfach zu schreiben.