Heiner Kücker

XML Really Pull Parser

Home

Java-Seite

 . Weiterentwicklung_Java

 . WebCam_Demo

 . JSP WorkFlow
 . PageFlow FlowControl
 . Page Flow Engine
 . Web Flow Engine
 . Control_and_Command

 . JSP_Spreadsheet

 . Kognitions-Maschine
 . semantisches Netz

 . Domain Parser

 . Codegenerator_für
 . hierarchische
 . Datenstrukturen

 . Expression_Engine
 . Formula_Parser

 . Thread Preprocessor

 . State Transition Engine

 . AspectJ

 . Java_Explorer

 . DBF_Library

 . Kalender_Applet

 . SetGetGen

 . BeanSetGet

 . CheckPackage

 . LineNumbers

 . GradDms

 . Excel-Export

 . StringTokenizer

 . JspDoc

 . JspCheck

 . JSP-Schulung
 . Java Server Pages
 . Struts

 . Ascii-Tabellen-
 . Layouter

 . Ascii-Baum-
 . Layouter

 . Ascii-Art-Fluss-
 . Diagramm-
 . Parser

 . AsciiArt
 . AssignmentMatrix
 . Layouter

 . StringSerial

 . Silbentrennung

 . JDBC_Schlüssel-
 . Generierung

 . bidirektional/
 . unidirektional
 . gelinkte Liste

 . Java_Sitemap
 . Generator

 . XmlBuilder

 . RangeMap

 . StringFormatter

 . VersionSafe
 . XCopy

 . JTextField

 . CommandLine-
 . ParamReader

 . Bitmap-Grafik

 . MultiMarkable-
 . Buffered-
 . InputStream

 . JavaCache

 . JdomUtil

 . CollectionUtil

 . XML Really
 . Pull Parser

 . Log-Filter

 . Remote-Protokoll

 . Sudoku-Generator

 . Delegation statt
 . Mehrfachvererbung

 . Disjunct
 . Interval Set

 . Constraint Class

 . Code Generator

Alaska-XBase++-Seite

Projekte

Philosophien
Techniken


Konzepte

Sudoku

Kontakt /
Impressum


Links

SiteMap





Letzte Aktualisierung:
15.06.2007
XML Really Pull Parser

Prototyp für einen XML-Parser, dessen Anwendugscode geanau die Struktur des XML-Dokumentes wiederspiegelt und keine Stack-Logik benötigt.

XML really pull parser
----------------------

Neben den SAX- und DOM-XML-Parsern gibt es die sogenannten XML-
Pull-Parser oder Streaming-Parser (StAX).

Beim XML-Pull-Parser wird noch nach Cursor- oder Iterator-
ähnlicher Verarbeitung unterschieden.

Die meisten XML-Pull-Parser werden folgendermassen angewendet
(Cursor-Verfahren):

while( parser.hasNext() ) {
    int event = parser.next();
    switch (event) {
        case XMLStreamConstants.END_DOCUMENT:
            System.out.println("END_DOCUMENT");
            parser.close();
            break;
        case XMLStreamConstants.START_ELEMENT:
            System.out.println("START_ELEMENT: " + parser.getLocalName() );
            for( int i = 0; i < parser.getAttributeCount(); i++ )
               System.out.println("Attribut: " + parser.getAttributeLocalName(i)
                                + " Wert: " + parser.getAttributeValue(i));
                                break;
        case XMLStreamConstants.CHARACTERS:
            if( !parser.isWhiteSpace() )
                System.out.println("CHARACTERS: " + parser.getText() );
            break;
        case XMLStreamConstants.END_ELEMENT:
            System.out.println("END_ELEMENT: " + parser.getLocalName() );
            break;
        default:
            break;
    }
}

Der Parser liefert beim Verarbeiten eine Reihe von Events.
Es gibt verschiedene Eventtypen.

START_DOCUMENT
END_DOCUMENT
START_ELEMENT
END_ELEMENT
CHARACTERS
ENTITY_REFERENCE
DTD
COMMENT
PROCESSING_INSTRUCTION

Zum Verarbeiten verschachtelter Strukturen muss eine Stack-Logik
aufgebaut werden.

Ich verstehe unter Pull-Parsing etwas anderes. Für eine
dreistufige Hierachie

 Haus -> Etage -> Wohnung

verwendet man die Lösung, welche naheliegend ist, nämlich drei
verschachtelte Schleifen (imperative Programmierung statt
deklarativer oder eventgetriebener Programmierung).

Deshalb habe ich hier mal einen anders aufgebauten XML-Parser,
XML-Really-Pull-Parser, prototypisch implementiert. Er ist sehr
untolerant bezüglich Fehlern oder Auslegungen im XML-Dokument,
dafür kommt er aber mit sehr wenig Ressourcen aus, weil zum
Beispiel unterschiedliche Reihenfolgen von Attributen nicht
erlaubt sind.

CDATA und innere DTD sind (noch) nicht implementiert, wie gesagt,
es ist ein Prototyp.

Das Parser-Anwendungsprogramm (das Programm welches das
konkretete XML-Dokument abarbeitet und die XRPP-Lib benutzt)
arbeitet sich vom Anfang an durch das XML-Dokument.

Die Struktur des XML spiegelt sich in der Struktur des Codes
wieder.

Irgendwelche Stack-Strukturen sind nicht nötig. Als Stack dient
der Java-Stack (lokale Variable, Parameter).

Optionale Element oder Attribute kosten zusätzlichen Code und
Performance. Andererseits werden bei einer stabilen XML-Struktur
sehr wenig Ressourcen verbraucht.

Beispiel für die Anwendung des XML Really Pull Parser
-----------------------------------------------------

Links die XML-Datei 'rss.xml' dargestelt und rechts der entsprechende Java-Quelltext zum Parsen 'TestRssXml.java'.

Wie man beim links rechts scrollen sehen kann, entspricht die Struktur des Java-Codes zum Parsen genau
der Struktur des XML-Dokumentes.

Dadurch ist das Programmieren eines XML-Parsers für ein bestimmtes festglegtes XML-Format sehr einfach.

rss.xml                                                               | TestRssXml.java
                                                                      |
<?xml version="1.0" encoding="ISO-8859-1"?>                           | parser.skipXmlDeclaration();
                                                                      |
<!DOCTYPE rss PUBLIC "-//Netscape Communications//DTD RSS 0.91//EN"   | parser.skipDoctypeDeclaration();
              "http://my.netscape.com/publish/formats/rss-0.91.dtd">  |
<rss                                                                  | parser.forceElementStart( "rss".getBytes() );
  version="0.91">                                                     | parser.getAttribute( "version".getBytes() );
                                                                      |
                                                                      | parser.forceElementBody();
                                                                      | {
  <channel>                                                           |   parser.forceElementStart( "channel".getBytes() );
                                                                      |   parser.forceElementBody();
                                                                      |   {
    <title>mars</title>                                               |     parser.getElementBodyWithStartAndEndTag( "title".getBytes() );
    <link>http://www.example.com/mars</link>                          |     parser.getElementBodyWithStartAndEndTag( "link".getBytes() );
    <description>Developer news from the MARS community</description> |     parser.getElementBodyWithStartAndEndTag( "description".getBytes() );
    <language>en-us</language>                                        |     parser.getElementBodyWithStartAndEndTag( "language".getBytes() );
    <copyright>Copyright 2999-3001, MARS team.</copyright>            |     parser.getElementBodyWithStartAndEndTag( "copyright".getBytes() );
    <managingEditor>editor@example.com</managingEditor>               |     parser.getElementBodyWithStartAndEndTag( "managingEditor".getBytes() );
    <webMaster>webmaster@example.com</webMaster>                      |     parser.getElementBodyWithStartAndEndTag( "webMaster".getBytes() );
                                                                      |
    <image>                                                           |     parser.forceElementStart( "image".getBytes() );
                                                                      |     parser.forceElementBody();
                                                                      |     {
      <title>mars</title>                                             |       parser.getElementBodyWithStartAndEndTag( "title".getBytes() );
      <url>http://www.example.com/images/mynetscape3188.gif</url>     |       parser.getElementBodyWithStartAndEndTag( "url".getBytes() );
      <link>http://www.example.com</link>                             |       parser.getElementBodyWithStartAndEndTag( "link".getBytes() );
      <width>88</width>                                               |       parser.getElementBodyWithStartAndEndTag( "width".getBytes() );
      <height>31</height>                                             |       parser.getElementBodyWithStartAndEndTag( "height".getBytes() );
      <description>News, and so on</description>                      |       parser.getElementBodyWithStartAndEndTag( "description".getBytes() );
                                                                      |     }
    </image>                                                          |     parser.forceElementStopNoEmpty( "image".getBytes() );
                                                                      |
    <item>                                                            |     while ( parser.isElementStart( "item".getBytes() ) )
                                                                      |     {
                                                                      |       parser.forceElementStart( "item".getBytes() );
                                                                      |       parser.forceElementBody();
                                                                      |       |
      <title>MARS 1.0 Released</title>                                |         parser.getElementBodyWithStartAndEndTag( "title".getBytes() );
      <link>http://www.example.com/read?item=3322323</link>           |         parser.getElementBodyWithStartAndEndTag( "link".getBytes() );
      <description>The MARS survival toolkit.</description>           |         parser.getElementBodyWithStartAndEndTag( "description".getBytes() );
                                                                      |       }
    </item>                                                           |       parser.forceElementStopNoEmpty( "item".getBytes() );
                                                                      |     }
                                                                      |   }
  </channel>                                                          |   parser.forceElementStopNoEmpty( "channel".getBytes() );
                                                                      | }
</rss>                                                                | parser.forceElementStopNoEmpty( "rss".getBytes() );
                                                                      |
TODO
Entwickeln eines Java-Programmes, zum Erzeugen des Parser-Codes
aus einem Beispiel-XML, wobei mehrfach mögliche Elemente jeweils
mindestens zweimal im Beispiel-XML notiert sein müssen, damit der
Code-Generator erkennt, dass sich das Element wiederholen kann.

Weiterführende Überlegung

Die Entscheidung für einen stream-baiserten Parser (SAX, Stax usw), statt eines document-basierten Parsers, zwingt dem Entwickler die Arbeitsweise des jeweiligen Parsers auf.
Viel angenehmer wäre ein Parser, der es erlaubt grosse Datenmengen stream-basiert einzulesen, aber für ein bestimmtes Elemente einen DOM-Abschnitt festzulegen.
Dieser Abschnitt (ein bestimmtes Element) erlaubt dann partielles freies Navigieren in den XML-Daten.
Im Speicher muss nur der jeweilige DOM-Abschnitt gehalten werden.
Dies wäre ein guter Kompromiss zwischen Speicherbedarf und freier Navigierbarkeit und würde die Anwendung des Parsers erleichtern.
Ein Beispiel wäre ein mehrere Mega-Byte grosser Produkt-Katalog, aus dem jeweils das Artikel-Element als DOM-Area geschnitten wird.

Siehe hierzu auch XmlBuilder, XmlDocument

Siehe hierzu auch JdomUtil

Download der Quelldateien Xrpp.zip

Achtung: Erweiterungen und Fixes stelle ich ohne Historie und ohne Ankündigung hier bereit.
Deshalb am besten immer die letzte Version runterladen.

Lizenzbedingungen:

Die Programme, Quelltexte und Dokumentationen können ohne irgendwelche Bedingungen kostenlos verwendet werden.
Sie sind Freeware und Open Source. Für Fehler und Folgen wird keinerlei Haftung übernommen.

Hinweise zur Fehlerbeseitigung und Verbesserung sind mir willkommen.

Ich freue mich auch über Feedback bezüglich der erfolgreichen Verwendung meiner Sourcen.

Bei Fragen helfe ich gern mit Hinweisen oder zusätzlicher Dokumentation, falls ich dafür Zeit habe.