Heiner KückerXML Really Pull Parser | 
   |
| 
     
     Home Java-Seite Bit Packed Array ASM Improved heterogene Map, HMap Constraint Code Generator JSP WorkFlow PageFlow FlowControl Page Flow Engine Web Flow Engine Control_and_Command JSP_Spreadsheet Code-Generator für Option-Either-Stil in Java verbesserter Comparator Fluent-Interface Code-Generator auf Basis einer Grammatik Visitor mit Multidispatch for-Schleife mit yield-return 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 WebCam_Demo Weiterentwicklung_Java 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
 
Siehe hierzu auch
XmlBuilder, XmlDocument 
Siehe hierzu auch
JdomUtil 
Achtung: Erweiterungen und Fixes stelle ich ohne Historie
und ohne Ankündigung hier bereit. Lizenzbedingungen: 
Die Programme, Quelltexte und Dokumentationen können ohne
irgendwelche Bedingungen kostenlos verwendet werden.  |