Außer unter den im Folgenden genannten spezifischen Links finden Sie weitere Erläuterungen auch unter:
http://docs.oracle.com/cd/E17802_01/webservices/webservices/docs/2.0/tutorial/doc
Möglicherweise interessante Bücher:
Einstieg in XML (Aktuelle Standards, XML Schema, XSL, XLink), Helmut Vonhoegen, 2009, ISBN 3836213672
Java und XML (Grundlagen, Einsatz, Referenz), Michael Scholz und Stephan Niedermeier, 2009, ISBN 3836213087
Bekannte Tools:
Altova XMLSpy,
Stylus Studio und
Liquid XML Studio
XML definiert, wie Daten strukturiert in Textdateien gespeichert werden. XML-Datenstrukturen sind auch für andere als die ursprüngliche Anwendung verständlich. Daten können plattformunabhängig zwischen verschiedenen Anwendungen ausgetauscht werden. XML ist als Metasprache erweiterbar und ist ebenso wie HTML und XHTML eine Untermenge von SGML. XML 1.0 wurde Anfang 1998 vom W3C als Standard verabschiedet.
Eine einfache XML-Datei kann zum Beispiel so aussehen:
<?xml version="1.0" encoding="UTF-8"?> <MeinRootElement> <MeinErstesUnterElement MeinAttribut="Attributwert"> Elementinhalt </MeinErstesUnterElement> <MeinLeeresUnterElement/> </MeinRootElement>
XML-Dateien beginnen normalerweise mit einer oder mehreren durch "<?" gekennzeichneten "PI" (Processing Instruction), die Hinweise zur Verarbeitung enthält.
Es kann mehrere Unterelemente geben, aber nur genau ein Root-Element. Die Elemente können Attribute und/oder Inhalte enthalten. Ist der Inhalt (auch Rumpf genannt) leer, ist auch die bei "<MeinLeeresUnterElement/>" gezeigte verkürzte Schreibweise möglich.
Es gibt fünf reservierte Zeichen, die in Attributen und Inhalten normalerweise nicht verwendet werden dürfen,
sondern als Entity-Referenz ausgedrückt werden müssen:
& = &, < = <, > = >, " = ", ' = '.
Nicht im angegebenen Encoding
enthaltene Sonderzeichen können als Unicode-Zeichenreferenz angegeben werden, zum Beispiel "€" für "€".
Nicht vom XML-Parser zu interpretierender Text muss mit "<![CDATA[ ... ]]>" als "Character Data" eingeschlossen werden.
Siehe auch:
http://www.w3.org/XML,
http://www.w3.org/TR/xml und
http://www.w3.org/TR/xml11
XML-Namespaces ("xmlns") sind Namensräume, vergleichbar in etwa mit den Packages in Java. Damit bestimmte Bezeichner in verschiedenen Zusammenhängen mit unterschiedlicher Bedeutung benutzt werden können, macht XML ausgiebig Gebrauch vom Konzept der Namespaces.
Als Konvention gilt, dass als Bezeichner des Namespaces ein Text in Form einer URL verwendet wird. Dabei bedeutet diese URL nicht, dass es eine entsprechende Webseite gibt.
Eine einfache XML-Datei mit Namespaces kann zum Beispiel so aussehen:
<?xml version="1.0" encoding="UTF-8"?> <mns:MeinRootElement xmlns:mns="http://meinnamespace.meinefirma.de"> <mns:MeinUnterElement mns:MeinAttribut="Attributwert"> Elementinhalt </mns:MeinUnterElement> </mns:MeinRootElement>
Siehe auch:
http://www.w3.org/TR/xml-names
http://www.w3.org/TR/xml-names11
Definition der Dokumentenart und der Bedeutung der Tags bei HTML- und XML-Dokumenten. Auf die DTD wird per DOCTYPE-Anweisung verwiesen. DTD wird zunehmend durch das leistungsfähigere XML Schema ersetzt.
Siehe auch:
http://www.w3.org/TR/REC-xml
XML Schema definiert Art und Struktur von XML-Dokumenten und den enthaltenen Elementen und ermöglicht eine Validierung. Ein XML Schema wird als XML Schema Definition in einer XML-Datei mit der Dateiendung .xsd gespeichert. XML Schemas sind wesentlich leistungsfähiger als DTDs und ersetzen diese zunehmend.
Eine einfaches XSD-Schema kann zum Beispiel so aussehen:
<?xml version="1.0" encoding="ISO-8859-1"?> <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" targetNamespace="http://meinnamespace.meinefirma.de" xmlns="http://meinnamespace.meinefirma.de" elementFormDefault="qualified"> <xsd:element name="MeinRootElement"> <xsd:complexType> <xsd:sequence> <xsd:element name="MeinUnterElement" type="xsd:string" /> </xsd:sequence> </xsd:complexType> </xsd:element> </xsd:schema>
Der xmlns:xsd-Namensraum muss für XSD immer wie angegeben definiert werden.
Der Bezeichner xsd könnte auch anders gewählt werden (z.B. xs).
Der targetNamespace muss dem im Ziel-Instanzdokument verwendeten Namespace entsprechen.
xmlns definiert den Default-Namespace dieser XSD-Schema-Datei
(ein Default-Namespace
gilt nur für Elemente und nicht für Attribute).
In einfachen Fällen können die targetNamespace- und xmlns-Angaben auch entfallen.
Ein einfaches dieses Schema verwendendes XML-Dokument (eine so genannte "Instanz") kann zum Beispiel so aussehen:
<?xml version="1.0" encoding="ISO-8859-1"?> <MeinRootElement xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://meinnamespace.meinefirma.de http://www.meinefirma.de/MeinSchema.xsd" xmlns="http://meinnamespace.meinefirma.de"> <MeinUnterElement> Elementinhalt </MeinUnterElement> </MeinRootElement>
Der xmlns:xsi-Namensraum muss für XSI immer wie angegeben definiert werden.
xsi:schemaLocation enthält zwei durch Leerzeichen getrennte Teile:
Zuerst wird der im XSD-Schema definierte targetNamespace angegeben und dann die Datei des XSD-Schemas,
entweder als Datei im lokalen Dateisystem oder alternativ wie hier im Beispiel als URL
(die in diesem Fall natürlich auf eine tatsächlich vorhandene und verfügbare Datei verweisen muss).
xmlns definiert den Default-Namespace der Elemente in dieser XML-Datei
(ein Default-Namespace
gilt nur für Elemente und nicht für Attribute).
Falls Sie die Validierung zum Beispiel mit Eclipse testen wollen: Speichern Sie das XSD-Schema in MeinSchema.xsd und das XML-Instanzdokument in MeinDokument.xml, ändern Sie in MeinDokument.xml die Schema-Location von http://www.meinefirma.de/MeinSchema.xsd zu MeinSchema.xsd und wählen Sie in Eclipse "Validate", indem Sie mit der rechten Maustaste entweder auf den Verzeichnisnamen oder in das XML-Instanzdokument klicken.
Wenn Sie innerhalb eines Java-Programms validieren möchten, können Sie beispielsweise DocumentBuilderFactory.setSchema(), SAXParserFactory.setSchema() oder Validator.validate() verwenden.
Ausführlichere Beispiele finden Sie unter XSD (XML Schema Definition) und Validierung.
Eine erste Einführung zum XML Schema finden Sie unter http://de.wikipedia.org/wiki/XML_Schema. Genaueres finden Sie im englischen Original in der W3C XML Schema Specification unter http://www.w3.org/XML/Schema oder ins deutsche übersetzt unter Einführung, Strukturen und Datentypen.
Java-Klassen hierzu finden Sie in
http://docs.oracle.com/javase/7/docs/api/javax/xml/validation/package-summary.html
Die XSL-Spezifikation des W3C enthält die drei Unterspezifikationen XPath, XSLT und XSL-FO.
XPath bietet eine Syntax für Lokalisierungspfade zur Identifikation von Elementen und Attributen in XML-Dokumenten. XPath wird zum Beispiel bei XML Schema, XSLT, XPointer und XForms verwendet.
XSL definiert eine Sprache für Umwandlungsregeln.
XSLT beschreibt, wie XML-Dokumente in andere Formate transformiert werden können.
XSL-FO spezifiziert, wie die grafische Aufbereitung von XML-Dokumenten beschrieben wird und enthält Anweisungen zur Formatierung und Präsentation der Daten.
Apache FOP ist eine Implementierung von XSL-FO und erstellt aus XSL-FO-Layout-Beschreibungen verschiedene Ausgabeformate, zum Beispiel PDF, Java2D/AWT, AFP, PCL, MIF, PS, RTF, TIFF, PNG, SVG und TXT.
TrAX wird manchmal als Oberbegriff für die Transformations-APIs verwendet.
Ein einfaches XSL-Stylesheet kann zum Beispiel so aussehen:
<?xml version="1.0" encoding="ISO-8859-1"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output method="xml" version="1.0" indent="yes" encoding="ISO-8859-1" /> <xsl:template match="MeinRootElement"> <MeinNeuesRootElement> <MeinNeuesUnterElement><xsl:value-of select="MeinUnterElement"/></MeinNeuesUnterElement> </MeinNeuesRootElement> </xsl:template> </xsl:stylesheet>
Auch wenn man es in diesem einfachen Beispiel nicht erkennen kann: Bei "<xsl:value-of select="..."/>" ist ein XPath-Ausdruck eingesetzt.
Für einen einfachen Test speichern Sie das XSL-Stylesheet in MeinStylesheet.xsl und erzeugen folgende Input.xml:
<?xml version="1.0" encoding="ISO-8859-1"?> <MeinRootElement> <MeinUnterElement>Elementinhalt</MeinUnterElement> </MeinRootElement>
Die XSL-Transformation kann mit beliebigen XSLT-Transformationstools erfolgen, beispielsweise:
Transformation mit Eclipse: Klicken Sie in Eclipse mit der rechten Maustaste auf MeinStylesheet.xsl, wählen Sie 'Run As' | 'XSL Transformation' und wählen Sie als 'XML Input File' über die Schaltflächen die XML-Datei Input.xml.
Transformation mit Xalan: Downloaden Sie Xalan, kopieren Sie xalan.jar und serializer.jar zu den beiden XML-Dateien und rufen Sie auf:
java -cp xalan.jar;serializer.jar org.apache.xalan.xslt.Process -XSL MeinStylesheet.xsl -IN Input.xml -OUT Result.xml
Transformation unter Windows mit MSXML: Downloaden Sie den Microsoft-MSXML-Wrapper msxsl.exe und rufen Sie auf:
msxsl Input.xml MeinStylesheet.xsl -o Result.xml
Ausführlichere Beispiele finden Sie unter XSL, XSLT, XSL-FO, FOP.
Siehe auch:
http://www.w3schools.com,
http://xml.klute-thiemann.de,
http://www.w3.org/Style/XSL,
http://www.w3.org/TR/xsl,
http://www.w3.org/TR/xslt,
http://docs.oracle.com/javase/7/docs/api/javax/xml/transform/package-summary.html und
http://docs.oracle.com/javase/7/docs/api/javax/xml/xpath/package-summary.html
DOM ist ein W3C-Standard für eine Programmierschnittstelle für verschiedene Programmiersprachen zur XML-Verarbeitung. DOM konkurriert mit SAX und StAX. Anders als bei SAX und StAX erfolgt bei DOM der XML-Zugriff über einen Objektbaum, was komfortabler ist, aber nicht für große Dokumente geeignet ist. Per DOM können XML-Dokumente sowohl gelesen als auch erzeugt werden.
Siehe auch:
http://www.w3.org/DOM und
http://docs.oracle.com/javase/7/docs/api/org/w3c/dom/package-summary.html
SAX ist eine Programmierschnittstelle für verschiedene Programmiersprachen zur XML-Verarbeitung. SAX konkurriert mit StAX und DOM. Anders als bei DOM wird bei SAX das XML-Dokument sequentiell durchlaufen, so dass auch sehr große Dokumente bearbeitet werden können. Ereignisgesteuert werden bei bestimmten Inhalten vorher (per DocumentHandler-Schnittstelle) registrierte Callbackfunktionen aufgerufen (event-based Parser, "Push-Parsing"). Anders als bei DOM können mit SAX XML-Dokumente nur gelesen aber nicht erzeugt werden.
Siehe auch:
http://www.saxproject.org und
http://docs.oracle.com/javase/7/docs/api/org/xml/sax/package-summary.html
StAX ist eine Programmierschnittstelle für verschiedene Programmiersprachen zur XML-Verarbeitung. StAX konkurriert mit SAX und DOM. Ähnlich wie bei SAX wird auch bei StAX das XML-Dokument sequentiell durchlaufen, so dass auch sehr große Dokumente bearbeitet werden können. Während bei SAX registrierte Callbackfunktionen aufgerufen werden, also der Parser das Anwendungsprogramm aufruft ("Push-Parsing"), wird bei StAX "andersherum" verfahren: Das Anwendungsprogramm ruft iterativ den Parser auf ("Pull-Parsing"). Dies hat den Vorteil, dass nicht wie bei SAX mühsam der Zusammenhang zwischen den isolierten Callbackfunktionen zum Beispiel über State Machines hergestellt werden muss, sondern die Kontrolle beim Entwickler bleibt und einfachere iterative Schleifen programmiert werden können. Anders als bei SAX können mit StAX XML-Dokumente sowohl gelesen als auch erzeugt werden.
Siehe auch:
http://jcp.org/en/jsr/detail?id=173,
http://docs.oracle.com/cd/E17802_01/webservices/webservices/docs/2.0/tutorial/doc/StAX2.html,
http://docs.oracle.com/javase/7/docs/api/javax/xml/stream/package-summary.html.
Web Services ermöglichen Abwicklungen von Dienstleistungen und Geschäften über das Internet. Web Services im engeren technischen Sinn meint automatisierte Kommunikation zwischen Applikationen über Netzwerke, beispielsweise übers Internet. Es werden also nicht HTML-Seiten zu einem Webbrowser geschickt, die von einem Menschen betrachtet werden, sondern Programme tauschen Daten und starten auf entfernten Rechnern Funktionen (Remote Procedure Call). Web Services basieren meistens auf den Standards SOAP, WSDL und UDDI.
Siehe auch:
http://www.w3.org/2002/ws,
http://www.w3.org/TR/soap und
techdocs/soap.htm
Java WSDP schnürte ursprünglich die Module JAXP, JAX-RPC, JAXR, JSTL, Java WSDP Registry Server, Web Application Deployment Tool, Ant Build Tool und den Apache Tomcat Container zu einem Paket zusammen.
Seit Java WSDP 2.0 enthält der "integrated Stack" die "Key Components" JAX-WS (Java API for XML Web Services), JAXB (Java API for XML Binding), SAAJ (SOAP with Attachments API for Java) und XWSS (XML Web Services Security).
Auch wenn man keine Web Services implementieren will, sondern nur XML behandeln will, lohnt sich ein Blick in die entsprechenden Kapitel des im Folgenden und auch an anderen Stellen in diesem Dokument aufgeführten 'Java Web Services Tutorials' von Sun, welches sowohl als HTML-Online-Doku, als PDF-Datei und als Buch erhältlich ist.
Siehe auch:
http://www.oracle.com/technetwork/java/index-jsp-137004.html
http://docs.oracle.com/cd/E17802_01/webservices/webservices/docs/2.0/tutorial/doc
http://docs.oracle.com/cd/E17802_01/webservices/webservices/docs/2.0/tutorial/doc/JavaWSTutorialTOC.html
Seit Java SE 6 und Java EE 5 sind die wichtigsten XML-APIs bereits enthalten.
Programmierbeispiele finden Sie unter SOAP Web Services mit JAX-WS.
Siehe auch:
http://jax-ws.java.net
http://www.ws-i.org/Profiles/BasicProfile-1.1.html
http://wsit.java.net
http://docs.oracle.com/cd/E17802_01/webservices/webservices/docs/2.0/jaxws/index.html
http://jax-ws.java.net/nonav/2.1.1/docs/api/index.html
Einheitliches API, um unter Java auf XML zuzugreifen. Umfasst DOM, SAX, StAX, Validierung, XSLT und XPath und kann verschiedene XML-Parser einbinden (über einen 'pluggability Layer'). JAXP ist seit J2SE 1.4 enthalten, aber erst in Java SE 6 zum Beispiel mit StAX vervollständigt.
Siehe auch:
http://jaxp.java.net
http://java.net/projects/jaxp-sources
http://java.sun.com/developer/codesamples/xml.html
http://people.apache.org/~edwingo/jaxp-ri-1.2.0-fcs/docs/samples.html
XML-Binding abstrahiert von der dokumentnahen Verarbeitung von XML-Dateien. Stattdessen werden XML-Strukturen auf Java-Klassenstrukturen gemappt (ähnlich wie beim Datenbank-O/R-Mapping).
Dazu gehören folgende vier Schwerpunkte:
JAXB ist oft das optimale Hilfsmittel zur Kommunikation per XML. Allerdings gibt es eine wichtige Einschränkung: Bei "normaler" Anwendung lädt JAXB das gesammte XML-Dokument in den Hauptspeicher, was bei großen Datenmengen zur Beeinträchtigung anderer Prozesse oder sogar zum OutOfMemoryError führen kann. In solchen Fällen kann es empfehlenswert sein, JAXB mit StAX zu kombinieren.
JAXB 2.0 ist ab Java SE 6 und ab Java EE 5 enthalten.
Siehe auch:
http://jaxb.java.net
http://docs.oracle.com/javase/7/docs/api/javax/xml/bind/package-summary.html
http://docs.oracle.com/cd/E17802_01/webservices/webservices/docs/2.0/tutorial/doc/JAXBWorks.html
http://docs.oracle.com/cd/E17802_01/webservices/webservices/docs/2.0/tutorial/doc/JAXBUsing.html
Vergleich von JAXB mit Apache XMLBeans, ADB und JiBX
Phillip Ghadir zu XML und JAXB
Xerces ist ein XML-Parser, der zum Beispiel über JAXP verwendet werden kann. Wenn keine besonderen Anforderungen vorliegen, kann einfach das JAXP-API mit dem bereits im JAXP enthaltenen Default-Parser verwendet werden, ohne dass man wissen muss, welcher Parser zu Grunde liegt.
Infos zu Xerces2 finden Sie unter:
http://xerces.apache.org/xerces2-j
Um die von Ihrer Java-Version verwendete Version von Xerces2-J zu ermitteln, rufen Sie auf:
java com.sun.org.apache.xerces.internal.impl.Version
Falls Sie weitere Infos benötigen, rufen Sie auf:
java com.sun.org.apache.xalan.internal.xslt.EnvironmentCheck
Sie können Ihr Java auch mit einem anderen XML-Parser/Builder verwenden. Hierzu setzen Sie entweder eine Environment-Variable, beispielsweise so ähnlich wie:
-Djavax.xml.parsers.SAXParserFactory=MeineKlasse
Oder alternativ per "Endorsed Standards Override Mechanism", indem Sie im <java-home>/lib/endorsed-Verzeichnis Ihre gewünschten Versionen von xalan.jar, serializer.jar, xercesImpl.jar und xml-apis.jar ablegen.
JDOM ist eine Open-Source-Java-Bibliothek, die eine an Java angepasste Programmierschnittstelle bietet und einen an Java angepassten Objekt-Tree aus dem XML-Dokument erstellt.
dom4j ist ebenfalls Open-Source und eine Alternative, die besonders viele Features beinhaltet.
Siehe auch:
http://www.jdom.org
http://www.servlets.com/speaking/jdom-javaone.pdf
http://www.cafeconleche.org/books/xmljava/chapters/ch14.html
http://www.javaworld.com/javaworld/jw-05-2000/jw-0518-jdom.html
http://www.jdom.org/docs/apidocs
JSR 102
http://www.dom4j.org
Speichern Sie das folgende XML-Dokument unter dem Namen: 'MyXmlFile.xml':
<?xml version='1.0' encoding='UTF-8'?> <!-- MyXmlFile.xml --> <GUI-Description> <Button size="normal" x="70" y="80"> <Title>Mein erster Button</Title> <Action>call Fct1</Action> <Comment/> </Button> <Button size="small"> <Title>Mein zweiter Button</Title> <Action>call Fct2</Action> </Button> <Button size="big"> <Action>call Fct3</Action> <Title>Mein dritter Button</Title> <Comment>Dies ist <b>HTML</b>-<i>Text</i>.</Comment> </Button> </GUI-Description>
Wie oben bereits erläutert wurde, ist StAX eine Programmierschnittstelle zur XML-Verarbeitung. Anders als bei SAX können mit StAX XML-Dokumente sowohl gelesen als auch erzeugt werden. Wie bei SAX wird auch bei StAX das XML-Dokument sequentiell durchlaufen. Anders als bei SAX ruft der Programmierer iterativ den Parser auf ("Pull-Parsing").
Im selben Verzeichnis, in dem sich obige Beispiel-XML-Datei 'MyXmlFile.xml' befindet, speichern Sie für das erste StAX-Beispiel den folgenden Java-Sourcecode unter dem Namen 'StaxToXPathProperties.java':
// StaxToXPathProperties.java import java.util.*; import javax.xml.stream.*; import javax.xml.stream.events.*; import javax.xml.transform.stream.StreamSource; public class StaxToXPathProperties { @SuppressWarnings("unchecked") public static void main( String[] args ) throws XMLStreamException { if( args.length != 1 ) { System.err.println( "Bitte XML-Datei angeben, beispielsweise:" ); System.err.println( " java StaxToXPathProperties MyXmlFile.xml" ); return; } XMLInputFactory inputFactory = XMLInputFactory.newInstance(); XMLEventReader evRd = inputFactory.createXMLEventReader( new StreamSource( args[0] ) ); Stack<String> stck = new Stack<String>(); while( evRd.hasNext() ) { XMLEvent ev = evRd.nextEvent(); if( ev.isStartElement() ) { stck.push( ev.asStartElement().getName().getLocalPart() ); Iterator<Attribute> iter = ev.asStartElement().getAttributes(); while( iter.hasNext() ) { Attribute a = iter.next(); System.out.println( buildXPathString( stck, "/@" + a.getName().getLocalPart() + "=\"" + a.getValue() + "\"" ) ); } } if( ev.isCharacters() ) { String s = ev.asCharacters().getData(); if( s.trim().length() > 0 ) System.out.println( buildXPathString( stck, "=\"" + s + "\"" ) ); } if( ev.isEndElement() ) stck.pop(); } } private static String buildXPathString( Stack<String> stck, String postfix ) { StringBuffer sb = new StringBuffer(); for( String s : stck ) sb.append( "/" ).append( s ); sb.append( postfix ); return sb.toString(); } }
Öffnen Sie ein Kommandozeilenfenster ('Windows-Taste' + 'R', 'cmd'), wechseln Sie in Ihr Projektverzeichnis und testen Sie das Programm mit einer beliebigen XML-Datei:
javac StaxToXPathProperties.java
java StaxToXPathProperties MyXmlFile.xml
Sie erhalten u.a.:
/GUI-Description/Button/@y="80" /GUI-Description/Button/@x="70" /GUI-Description/Button/@size="normal" /GUI-Description/Button/Title="Mein erster Button" /GUI-Description/Button/Action="call Fct1" /GUI-Description/Button/@size="small" /GUI-Description/Button/Title="Mein zweiter Button" /GUI-Description/Button/Action="call Fct2" ...
Eine Einführung zu StAX finden Sie im StAX-Tutorial. Das Programm verwendet das so genannte "Iterator API" von StAX. Alternativ gibt es noch das "Cursor API" (siehe folgendes Beispiel):
Im selben Verzeichnis, in dem sich obige Beispiel-XML-Datei 'MyXmlFile.xml' befindet, speichern Sie den folgenden Java-Sourcecode unter dem Namen 'StaxParseEvents.java':
// StaxParseEvents.java import java.util.*; import javax.xml.stream.*; import javax.xml.transform.stream.StreamSource; import static javax.xml.stream.XMLStreamConstants.*; public class StaxParseEvents { public static void main( String[] args ) throws XMLStreamException { if( args.length != 1 ) { System.err.println( "Bitte XML-Datei angeben, beispielsweise:" ); System.err.println( " java StaxParseEvents MyXmlFile.xml" ); return; } XMLInputFactory inputFactory = XMLInputFactory.newInstance(); XMLStreamReader stax = inputFactory.createXMLStreamReader( new StreamSource( args[0] ) ); Map<Integer,String> pem = (new StaxEventNames()).map; while( true ) { int pe = stax.getEventType(); System.out.print( pe + "-" + pem.get( new Integer( pe ) ) ); if( stax.hasName() ) { String s = ": "; if( stax.isEndElement() ) s += "/"; s += stax.getName(); if( stax.isStartElement() ) s += ":"; System.out.print( s ); } if( (pe == ATTRIBUTE || pe == START_ELEMENT) && stax.getAttributeCount() > 0 ) { for( int i = 0; i < stax.getAttributeCount(); i++ ) { System.out.print( " " + stax.getAttributeLocalName(i) + "=\"" + stax.getAttributeValue(i) + "\"" ); } } if( stax.hasText() ) System.out.print( ": " + stax.getText().trim() ); System.out.println( "" ); if( !stax.hasNext() ) break; stax.next(); } } } class StaxEventNames { public final Map<Integer,String> map; public StaxEventNames() { Map<Integer,String> pem = new HashMap<Integer,String>(); pem.put( new Integer( ATTRIBUTE ), "ATTRIBUTE " ); pem.put( new Integer( CDATA ), "CDATA " ); pem.put( new Integer( CHARACTERS ), "CHARACTERS " ); pem.put( new Integer( COMMENT ), "COMMENT " ); pem.put( new Integer( DTD ), "DTD " ); pem.put( new Integer( END_DOCUMENT ), "END_DOCUMENT " ); pem.put( new Integer( END_ELEMENT ), "END_ELEMENT " ); pem.put( new Integer( NAMESPACE ), "NAMESPACE " ); pem.put( new Integer( SPACE ), "SPACE " ); pem.put( new Integer( START_DOCUMENT ), "START_DOCUMENT" ); pem.put( new Integer( START_ELEMENT ), "START_ELEMENT " ); pem.put( new Integer( ENTITY_DECLARATION ), "ENTITY_DECLARATION " ); pem.put( new Integer( ENTITY_REFERENCE ), "ENTITY_REFERENCE " ); pem.put( new Integer( NOTATION_DECLARATION ), "NOTATION_DECLARATION " ); pem.put( new Integer( PROCESSING_INSTRUCTION ), "PROCESSING_INSTRUCTION" ); map = Collections.unmodifiableMap( pem ); } }
Öffnen Sie ein Kommandozeilenfenster ('Windows-Taste' + 'R', 'cmd'), wechseln Sie in Ihr Projektverzeichnis und testen Sie das Programm mit einer beliebigen XML-Datei:
javac StaxParseEvents.java
java StaxParseEvents MyXmlFile.xml
Sie erhalten u.a.:
7-START_DOCUMENT 5-COMMENT : MyXmlFile.xml 1-START_ELEMENT : GUI-Description: 4-CHARACTERS : 1-START_ELEMENT : Button: size="normal" x="70" y="80" 4-CHARACTERS : 1-START_ELEMENT : Title: 4-CHARACTERS : Mein erster Button 2-END_ELEMENT : /Title 4-CHARACTERS : 1-START_ELEMENT : Action: 4-CHARACTERS : call Fct1 2-END_ELEMENT : /Action ... 8-END_DOCUMENT
Das Programm verwendet das so genannte "Cursor API" von StAX. Alternativ gibt es noch das "Iterator API" (zum Unterschied siehe oben).
Bitte beachten Sie, dass (anders als beim Iterator API) das stax.next()-Kommando am Ende der Schleife stehen muss, damit Sie auch das erste START_DOCUMENT-Event sehen.
Doku zu StAX und zum XMLStreamReader finden Sie unter: StAX-Tutorial, javax.xml.stream und XMLStreamReader.
Im selben Verzeichnis, in dem sich obige Beispiel-XML-Datei 'MyXmlFile.xml' befindet, speichern Sie den folgenden Java-Sourcecode unter dem Namen 'ExampleStaxGetData.java':
// ExampleStaxGetData.java import java.io.File; import javax.xml.stream.*; import javax.xml.transform.stream.StreamSource; public class ExampleStaxGetData { public static void main( String[] args ) throws XMLStreamException { if( args.length != 5 ) { System.err.println( "Usage:" ); System.err.println( "java ExampleStaxGetData <XmlFile> " + "<ParentElem> <ChildElem> <FindText> <DataElem>" ); System.err.println( "Example:" ); System.err.println( "java ExampleStaxGetData MyXmlFile.xml " + "Button Title \"Mein dritter Button\" Comment" ); return; } XMLInputFactory inputFactory = XMLInputFactory.newInstance(); XMLStreamReader stax = inputFactory.createXMLStreamReader( new StreamSource( new File( args[0] ) ) ); StringBuffer sb = new StringBuffer(); int state = 0; while( stax.hasNext() ) { stax.next(); String name = ( stax.hasName() ) ? stax.getName().getLocalPart().trim() : null; String text = ( stax.hasText() ) ? stax.getText().trim() : null; boolean b1 = stax.hasName() && name.equals( args[1].trim() ); // <ParentElem> boolean b2 = stax.hasName() && name.equals( args[2].trim() ); // <ChildElem> boolean b3 = stax.hasText() && text.equals( args[3].trim() ); // <FindText> boolean b4 = stax.hasName() && name.equals( args[4].trim() ); // <DataElem> if( b1 && stax.isStartElement() ) state = 1; // <ParentElem> if( b1 && stax.isEndElement() ) state = 0; if( state == 1 && b2 && stax.isStartElement() ) state = 2; // <ChildElem> if( state == 2 && b2 && stax.isEndElement() ) state = 1; if( state == 2 && b3 ) state = 3; // <FindText> if( state == 3 && b4 && stax.isStartElement() ) state = 4; // <DataElem> if( state == 4 && b4 && stax.isEndElement() ) break; if( state == 4 && stax.hasText() ) sb.append( stax.getText() ); // gesuchtes Ergebnis } System.out.println( sb ); } }
Öffnen Sie ein Kommandozeilenfenster, wechseln Sie in Ihr Projektverzeichnis und testen Sie das Programm:
javac ExampleStaxGetData.java
java ExampleStaxGetData
java ExampleStaxGetData MyXmlFile.xml Button Title "Mein dritter Button" Comment
Falls Ihr Webbrowser ein Kommando auf zwei Zeilen umgebrochen hat: Bitte geben Sie diese als eine einzige Kommandozeile ein.
Die Kommandozeilenparameter haben folgende Bedeutung:
Parameter | Beispiel | Bedeutung |
<XmlFile> | MyXmlFile.xml | In dieser XML-Datei wird gesucht |
<ParentElem> | Button | Elemente mit diesem Tag-Namen werden untersucht |
<ChildElem> | Title | Das gesuchte Element muss ein Child-Element mit diesem Tag-Namen haben |
<FindText> | "Mein dritter Button" | Das Child-Element muss diesen Text als Inhalt haben |
<DataElem> | Comment | Der Textinhalt dieses Elements wird ausgelesen |
Mit der Beispiel-XML-Datei 'MyXmlFile.xml' und den angegebenen Beispielparametern wird das dritte <Button>-Element gefunden, da dessen <Title>-Text mit der Suchvorgabe <FindText>="Mein dritter Button" übereinstimmt. Der Inhalt des durch <DataElem> vorgegebenen <Comment>-Elements wird ausgelesen und im Kommandozeilenfenster ausgegeben. Sie erhalten als Ergebnis:
Dies ist HTML-Text.
Im selben Verzeichnis, wo sich die Beispiel-XML-Datei 'MyXmlFile.xml' befindet, speichern Sie den folgenden Java-Sourcecode unter dem Namen 'ExampleSaxEcho.java' und kompilieren und führen ihn im Kommandozeilenfenster aus mit:
javac ExampleSaxEcho.java
java ExampleSaxEcho MyXmlFile.xml
Dokumentation zu den JAXP-Klassen und Methoden finden Sie unter: http://java.net/projects/jaxp-sources.
// ExampleSaxEcho.java import java.io.*; import javax.xml.parsers.*; import org.xml.sax.*; import org.xml.sax.helpers.DefaultHandler; public class ExampleSaxEcho extends DefaultHandler { static final String sNEWLINE = System.getProperty( "line.separator" ); static private Writer out = null; private StringBuffer textBuffer = null; // ---- main ---- public static void main( String[] argv ) { if( argv.length != 1 ) { System.err.println( "Usage: java ExampleSaxEcho MyXmlFile.xml" ); System.exit( 1 ); } try { // Use an instance of ourselves as the SAX event handler DefaultHandler handler = new ExampleSaxEcho(); // Parse the input with the default (non-validating) parser SAXParser saxParser = SAXParserFactory.newInstance().newSAXParser(); saxParser.parse( new File( argv[0] ), handler ); System.exit( 0 ); } catch( Throwable t ) { t.printStackTrace(); System.exit( 2 ); } } // ---- SAX DefaultHandler methods ---- @Override public void startDocument() throws SAXException { echoString( sNEWLINE + "<?xml ...?>" + sNEWLINE + sNEWLINE ); } @Override public void endDocument() throws SAXException { echoString( sNEWLINE ); } @Override public void startElement( String namespaceURI, String localName, // local name String qName, // qualified name Attributes attrs ) throws SAXException { echoTextBuffer(); String eName = ( "".equals( localName ) ) ? qName : localName; echoString( "<" + eName ); // element name if( attrs != null ) { for( int i=0; i<attrs.getLength(); i++ ) { String aName = attrs.getLocalName( i ); // Attr name if( "".equals( aName ) ) aName = attrs.getQName( i ); echoString( " " + aName + "=\"" + attrs.getValue( i ) + "\"" ); } } echoString( ">" ); } @Override public void endElement( String namespaceURI, String localName, // local name String qName ) // qualified name throws SAXException { echoTextBuffer(); String eName = ( "".equals( localName ) ) ? qName : localName; echoString( "</" + eName + ">" ); // element name } @Override public void characters( char[] buf, int offset, int len ) throws SAXException { String s = new String( buf, offset, len ); if( textBuffer == null ) textBuffer = new StringBuffer( s ); else textBuffer.append( s ); } // ---- Helper methods ---- // Display text accumulated in the character buffer private void echoTextBuffer() throws SAXException { if( textBuffer == null ) return; echoString( textBuffer.toString() ); textBuffer = null; } // Wrap I/O exceptions in SAX exceptions, to // suit handler signature requirements private void echoString( String s ) throws SAXException { try { if( null == out ) out = new OutputStreamWriter( System.out, "UTF8" ); out.write( s ); out.flush(); } catch( IOException ex ) { throw new SAXException( "I/O error", ex ); } } }
Im selben Verzeichnis, wo sich die oben gezeigte Beispiel-XML-Datei 'MyXmlFile.xml' befindet, speichern Sie den folgenden Java-Sourcecode unter dem Namen 'ExampleSaxGetData.java' und kompilieren und führen ihn aus mit:
javac ExampleSaxGetData.java
java ExampleSaxGetData MyXmlFile.xml Button Title "Mein dritter Button" Comment
Falls Ihr Webbrowser die mit "java" beginnende Zeile auf zwei Zeilen umgebrochen hat: Bitte geben Sie diese als eine einzige Kommandozeile ein.
Die Kommandozeilenparameter haben folgende Bedeutung:
Parameter | Beispiel | Bedeutung |
<XmlFile> | MyXmlFile.xml | In dieser XML-Datei wird gesucht |
<ParentElem> | Button | Elemente mit diesem Tag-Namen werden untersucht |
<ChildElem> | Title | Das gesuchte Element muss ein Child-Element mit diesem Tag-Namen haben |
<FindText> | "Mein dritter Button" | Das Child-Element muss diesen Text als Inhalt haben |
<DataElem> | Comment | Der komplette Inhalt dieses Child-Elements wird ausgelesen, auch inklusive Unterelementen (z.B. HTML-Tags) |
Mit der Beispiel-XML-Datei 'MyXmlFile.xml' und den angegebenen Beispielparametern wird das dritte <Button>-Element gefunden, da dessen <Title>-Text mit der Suchvorgabe <FindText>="Mein dritter Button" übereinstimmt. Der Inhalt des durch <DataElem> vorgegebenen <Comment>-Elements wird ausgelesen und im Kommandozeilenfenster ausgegeben.
Die Variable 'iState' dient als Statusspeicher. Etwas unübersichtlich wird der Status dadurch, dass das gesuchte Element inklusive seiner Unterelemente ausgelesen werden soll (im Beispiel der String 'Dies ist <b>HTML</b>-<i>Text</i>.').
Das Programm funktioniert nur mit einfachen XML-Dateien und ohne Unterstützung von Namespaces.
// ExampleSaxGetData.java import java.io.*; import javax.xml.parsers.*; import org.xml.sax.*; import org.xml.sax.helpers.DefaultHandler; public class ExampleSaxGetData { public static void main( String[] args ) { if( args.length != 5 ) { System.err.println( "Usage:" ); System.err.println( "java ExampleSaxGetData <XmlFile> " + "<ParentElem> <ChildElem> <FindText> <DataElem>" ); System.err.println( "Example:" ); System.err.println( "java ExampleSaxGetData MyXmlFile.xml " + "Button Title \"Mein dritter Button\" Comment" ); System.exit( 1 ); } try { MyDefaultHandlerImpl handler = new MyDefaultHandlerImpl(); handler.args = args; SAXParser saxParser = SAXParserFactory.newInstance().newSAXParser(); saxParser.parse( new File( args[0] ), handler ); if( 0 < handler.sbResult.length() ) { System.out.println( "Result string in child element '<" + args[4] + ">':" ); System.out.println( handler.sbResult ); System.exit( 0 ); } else { System.out.println( "No fitting element found." ); System.exit( 2 ); } } catch( Throwable t ) { t.printStackTrace(); System.exit( 3 ); } } } // ---- SAX DefaultHandler ---- class MyDefaultHandlerImpl extends DefaultHandler { public String[] args; public StringBuffer sbResult = new StringBuffer(); private int iState = 0; @Override public void startElement( String namespaceURI, String localName, String qName, Attributes attrs ) throws SAXException { if( 5 <= iState ) return; String eName = ( "".equals( localName ) ) ? qName : localName; if( null != eName ) { if( eName.equals( args[1] ) ) // <ParentElem> iState = 1; if( 1 == iState && eName.equals( args[2] ) ) // <ChildElem> iState = 2; if( 4 == iState ) sbResult.append( "<" + eName + ">" ); if( 3 == iState && eName.equals( args[4] ) ) // <DataElem> iState = 4; } } @Override public void endElement( String namespaceURI, String localName, String qName ) throws SAXException { if( 5 <= iState ) return; String eName = ( "".equals( localName ) ) ? qName : localName; if( null != eName ) { if( eName.equals( args[1] ) ) // <ParentElem> iState = 0; if( 2 == iState && eName.equals( args[2] ) ) // <ChildElem> iState = 1; if( 4 == iState && eName.equals( args[4] ) ) // <DataElem> iState = 5; if( 4 == iState ) sbResult.append( "</" + eName + ">" ); } } @Override public void characters( char[] buf, int offset, int len ) throws SAXException { if( 5 <= iState ) return; String s = new String( buf, offset, len ); if( 2 == iState && s.equals( args[3] ) ) // <FindText> iState = 3; if( 4 == iState ) sbResult.append( s ); } }
Im selben Verzeichnis, wo sich die oben gezeigte Beispiel-XML-Datei 'MyXmlFile.xml' befindet, speichern Sie den folgenden Java-Sourcecode unter dem Namen 'ExampleDomShowNodes.java' und kompilieren und führen ihn im Kommandozeilenfenster aus mit:
javac ExampleDomShowNodes.java
java ExampleDomShowNodes MyXmlFile.xml Button
Dokumentation zu den JAXP-Klassen und Methoden finden Sie unter: http://java.net/projects/jaxp-sources.
// ExampleDomShowNodes.java import java.io.*; import org.xml.sax.*; import org.w3c.dom.*; import javax.xml.parsers.*; public class ExampleDomShowNodes { public static void main( String[] argv ) { if( argv.length != 2 ) { System.err.println( "Usage: java ExampleDomShowNodes <XmlFile> <TagName>" ); System.err.println( "Example: java ExampleDomShowNodes MyXmlFile.xml Button" ); System.exit( 1 ); } try { // ---- Parse XML file ---- DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); DocumentBuilder builder = factory.newDocumentBuilder(); Document document = builder.parse( new File( argv[0] ) ); // ---- Get list of nodes to given element tag name ---- NodeList ndList = document.getElementsByTagName( argv[1] ); printNodesFromList( ndList ); // printNodesFromList see below // ---- Error handling ---- } catch( SAXParseException spe ) { System.out.println( "\n** Parsing error, line " + spe.getLineNumber() + ", uri " + spe.getSystemId() ); System.out.println( " " + spe.getMessage() ); Exception e = ( spe.getException() != null ) ? spe.getException() : spe; e.printStackTrace(); } catch( SAXException sxe ) { Exception e = ( sxe.getException() != null ) ? sxe.getException() : sxe; e.printStackTrace(); } catch( ParserConfigurationException pce ) { pce.printStackTrace(); } catch( IOException ioe ) { ioe.printStackTrace(); } } // ---- Helper methods ---- private static void printObjIfVisible( String sValName, Object obj ) { if( null == obj ) return; String s = obj.toString(); if( null != s && 0 < s.trim().length() && !s.trim().equals( "\n" ) ) System.out.println( sValName + s ); } public static void printNodeInfos( String sNodeName, Node node ) { System.out.println( "\n---------------------- " + sNodeName ); if( null != node ) { printObjIfVisible( "getNodeType() = ", "" + node.getNodeType() ); printObjIfVisible( "getNodeName() = ", node.getNodeName() ); printObjIfVisible( "getLocalName() = ", node.getLocalName() ); printObjIfVisible( "getNodeValue() = ", node.getNodeValue() ); if( node.hasAttributes() ) printObjIfVisible( "getAttributes() = ", node.getAttributes() ); if( node.hasChildNodes() ) { printObjIfVisible( "getChildNodes() = ", node.getChildNodes() ); printObjIfVisible( "getFirstChild() = ", node.getFirstChild() ); } printObjIfVisible( "getPreviousSibling() = ", node.getPreviousSibling() ); printObjIfVisible( "getNextSibling() = ", node.getNextSibling() ); } System.out.println( "----------------------\n" ); } public static void printNodesFromList( NodeList ndList ) { for( int i=0; i<ndList.getLength(); i++ ) printNodeInfos( "ndList.item("+i+")", ndList.item(i) ); } }
Dieses Programmierbeispiel erfüllt die gleichen Anforderungen mit JAXP-DOM, wie das weiter unten folgende Programmierbeispiel 'ExampleJdomAddWrite.java' mit JDOM erfüllt, um den unterschiedlichen Programmieraufwand einschätzen zu können.
In einer XML-Datei wird ein bestimmtes Element gesucht, dessen Childelement einen bestimmten Text enthält. Vor dieses Element wird ein neues Element plaziert und das Ergebnis in eine neue XML-Datei gespeichert.
Im selben Verzeichnis, wo sich die oben gezeigte Beispiel-XML-Datei 'MyXmlFile.xml' befindet, speichern Sie den folgenden Java-Sourcecode unter dem Namen 'ExampleDomAddWrite.java' und kompilieren und führen ihn aus mit:
javac ExampleDomAddWrite.java
java ExampleDomAddWrite MyXmlFile.xml NewXmlFile.xml Button Title "Mein dritter Button" "Mein neuer Button"
Falls Ihr Webbrowser die mit "java" beginnende Zeile auf zwei Zeilen umgebrochen hat: Bitte geben Sie diese als eine einzige Kommandozeile ein.
Die Kommandozeilenparameter haben folgende Bedeutung:
Parameter | Beispiel | Bedeutung |
<XmlFile> | MyXmlFile.xml | Diese XML-Datei wird zu Beginn gelesen |
<NewFile> | NewXmlFile.xml | In diese XML-Datei wird das Ergebnis geschrieben (falls die Suchbedingungen erfüllt werden) |
<ParentElem> | Button | Es werden Elemente mit diesem Tag-Namen gesucht |
<Child> | Title | Das gesuchte Element muss ein Child-Element mit diesem Tag-Namen haben |
<FindText> | "Mein dritter Button" | Das Child-Element muss diesen Text als Inhalt haben |
<New> | "Mein neuer Button" | Nur wenn die vorhergehenden Suchbedingungen erfüllt sind, wird ein neues Element mit diesem Child-Element-Inhalt vor das gefundene Element eingefügt |
Mit der Beispiel-XML-Datei 'MyXmlFile.xml' und den angegebenen Beispielparametern wird das dritte <Button>-Element gefunden, da dessen <Title>-Text mit der Suchvorgabe <FindText>="Mein dritter Button" übereinstimmt. Vor dieses <Button>-Element wird ein neues <Button>-Element mit dem angegebenen <Title>-Text <New>="Mein neuer Button" eingefügt. Das Ergebnis wird in die Datei 'NewXmlFile.xml' gespeichert, allerdings in wenig schöner Formatierung. Eine schönere Formatierung ist leicht mit JDOM realisierbar, wie die weiter unten gezeigten 'JDOM-Programmierbeispiele' demonstrieren.
Wenn Sie aus dem vorherigen Beispiel die Hilfsmethode 'printNodesFromList()' zu diesem Beispiel hinzufügen, können Sie an zwei Stellen die Kommentarzeichen '//' vor diesen Methodenaufrufen entfernen. Dann bekommen Sie die Knotenstruktur vor und nach der Änderung direkt im Kommandozeilenfenster angezeigt.
Das Beispielprogramm funktioniert für einfache XML-Dateien ohne Namespaces.
// ExampleDomAddWrite.java import java.io.*; import org.xml.sax.*; import org.w3c.dom.*; import javax.xml.parsers.*; import javax.xml.transform.*; import javax.xml.transform.dom.DOMSource; import javax.xml.transform.stream.StreamResult; public class ExampleDomAddWrite { public static void main( String[] argv ) { if( argv.length != 6 ) { System.err.println( "Usage:" ); System.err.println( "java ExampleDomAddWrite <XmlFile> <NewFile>" + " <ParentElem> <Child> <FindText> <New>" ); System.err.println( "Example:" ); System.err.println( "java ExampleDomAddWrite MyXmlFile.xml NewXmlFile.xml" + " Button Title \"Mein dritter Button\"" + " \"Mein neuer Button\"" ); System.exit( 1 ); } try { // ---- Parse XML file ---- DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); // factory.setNamespaceAware( true ); DocumentBuilder builder = factory.newDocumentBuilder(); Document document = builder.parse( new File( argv[0] ) ); Node rootNode = document.getDocumentElement(); // ---- Get list of nodes to given tag ---- NodeList ndList = document.getElementsByTagName( argv[2] ); // System.out.println( "\nNode list at the beginning:" ); // printNodesFromList( ndList ); // ---- Loop through the list of main nodes ---- for( int i=0; i<ndList.getLength(); i++ ) { Node nodeMain = ndList.item( i ); Node nodeChild = null; NodeList ndListChilds = nodeMain.getChildNodes(); boolean bChildFound = false; if( null == ndListChilds ) continue; // Loop through the list of child nodes for( int j=0; j<ndListChilds.getLength(); j++ ) { nodeChild = ndListChilds.item( j ); if( null == nodeChild ) continue; String sNodeName = nodeChild.getNodeName(); if( null == sNodeName ) continue; if( sNodeName.equals( argv[3] ) ) { bChildFound = true; break; } } if( !bChildFound || nodeChild == null ) continue; Node nodeData = nodeChild.getFirstChild(); if( null == nodeData || !(nodeData instanceof org.w3c.dom.Text) ) continue; String sData = nodeData.getNodeValue(); if( null == sData || !sData.equals( argv[4] ) ) continue; // ---- Create a new node element and insert it ---- Node newMainNode = document.createElement( argv[2] ); Node newChildNode = document.createElement( argv[3] ); Text newTextNode = document.createTextNode( argv[5] ); newChildNode.appendChild( newTextNode ); newMainNode.appendChild( newChildNode ); rootNode.insertBefore( newMainNode, nodeMain ); rootNode.normalize(); // System.out.println( "Node list after modification:" ); // printNodesFromList( ndList ); break; } // ---- Use a XSLT transformer for writing the new XML file ---- Transformer transformer = TransformerFactory.newInstance().newTransformer(); DOMSource source = new DOMSource( document ); FileOutputStream os = new FileOutputStream( new File( argv[1] ) ); StreamResult result = new StreamResult( os ); transformer.transform( source, result ); // ---- Error handling ---- } catch( TransformerConfigurationException tce ) { System.out.println( "\n** Transformer Factory error" ); System.out.println( " " + tce.getMessage() ); Throwable e = ( tce.getException() != null ) ? tce.getException() : tce; e.printStackTrace(); } catch( TransformerException tfe ) { System.out.println( "\n** Transformation error" ); System.out.println( " " + tfe.getMessage() ); Throwable e = ( tfe.getException() != null ) ? tfe.getException() : tfe; e.printStackTrace(); } catch( SAXParseException spe ) { System.out.println( "\n** Parsing error, line " + spe.getLineNumber() + ", uri " + spe.getSystemId() ); System.out.println( " " + spe.getMessage() ); Exception e = ( spe.getException() != null ) ? spe.getException() : spe; e.printStackTrace(); } catch( SAXException sxe ) { Exception e = ( sxe.getException() != null ) ? sxe.getException() : sxe; e.printStackTrace(); } catch( ParserConfigurationException pce ) { pce.printStackTrace(); } catch( IOException ioe ) { ioe.printStackTrace(); } } }
Weitere JAXP-Programmierbeispiele finden Sie unter:
http://java.sun.com/developer/codesamples/xml.html
http://people.apache.org/~edwingo/jaxp-ri-1.2.0-fcs/docs/samples.html
set JAVA_HOME=C:\Program Files\Java\jdk1.6
set Path=%JAVA_HOME%\bin;%Path%
set CLASSPATH=.;C:\Program Files\Java\jdk1.6\jre\lib\ext\jdom.jar
b) Oder Sie starten Ihr Programm über eine Batchdatei, in der Sie die genannte Zeile einfügen.java -classpath .;C:\Program Files\Java\jdk1.6\jre\lib\ext\jdom.jar MeinJavaProgr
Bei allen Alternativen ist wichtig, dass Sie im 'CLASSPATH' immer auch das aktuelle Verzeichnis mit angeben, der 'CLASSPATH' sollte also mit '.;' beginnen.Im selben Verzeichnis, wo sich die oben gezeigte Beispiel-XML-Datei 'MyXmlFile.xml' befindet, speichern Sie den folgenden Java-Sourcecode unter dem Namen 'ExampleJdomWrite.java' und kompilieren und führen ihn im Kommandozeilenfenster aus mit:
javac -classpath .;jdom.jar ExampleJdomWrite.java
java -classpath .;jdom.jar ExampleJdomWrite MyXmlFile.xml
Falls Sie 'jdom.jar' bereits im globalen 'CLASSPATH' eingetragen haben, können Sie den Teil '-classpath .;jdom.jar' in beiden Kommandos weglassen. Die gezeigte Schreibweise der Kommandos benötigt keinen vorher speziell gesetzten 'CLASSPATH', aber setzt voraus, dass die Datei 'jdom.jar' im selben Verzeichnis wie das Java-Programm gespeichert ist. Falls 'jdom.jar' woanders gespeichert ist, müssen Sie den Pfad voranstellen.
Dokumentation zu den JDOM-Klassen und Methoden finden Sie unter: http://www.jdom.org/docs/apidocs.
Anders als im oben gezeigtem DOM-Programmierbeispiel 'ExampleDomAddWrite.java' erfolgt hier die Ausgabe in schön formatierter Form.
Beachtenswert ist, dass zum Lesen ein SAX-Parser eingesetzt wird, damit kein zweiter DOM-Baum aufgebaut wird, der nur Speicherplatz verbrauchen würde. Trotzdem erfolgt die weitere Bearbeitung der XML-Daten über die JDOM-Baumstruktur.
// ExampleJdomWrite.java import java.io.*; import org.jdom.*; import org.jdom.input.*; import org.jdom.output.*; public class ExampleJdomWrite { public static void main( String[] args ) { if( args.length != 1 ) { System.err.println( "Usage: java ExampleJdomWrite MyXmlFile.xml" ); System.exit( 1 ); } try { // ---- Read XML file ---- SAXBuilder builder = new SAXBuilder(); Document doc = builder.build( new File( args[0] ) ); // ---- Modify XML data ---- // ... do anything with XML data // ---- Write XML file ---- XMLOutputter fmt = new XMLOutputter(); fmt.setFormat( Format.getPrettyFormat() ); // only for nicer formatting fmt.output( doc, System.out ); } catch( Exception ex ) { ex.printStackTrace(); } } }
Dieses Programmierbeispiel erfüllt die gleichen Anforderungen mit JDOM, wie das oben aufgeführte Programmierbeispiel 'ExampleDomAddWrite.java' mit JAXP-DOM erfüllt hat. Das JDOM-Beispiel erzeugt eine schön formatierte Ausgabe und ist kürzer und einfacher.
In einer XML-Datei wird ein bestimmtes Element gesucht, dessen Childelement einen bestimmten Text enthält. Vor dieses Element wird ein neues Element plaziert und das Ergebnis in eine neue XML-Datei gespeichert.
Im selben Verzeichnis, wo sich die oben gezeigte Beispiel-XML-Datei 'MyXmlFile.xml' befindet, speichern Sie den folgenden Java-Sourcecode unter dem Namen 'ExampleJdomAddWrite.java' und kompilieren und führen ihn aus mit:
javac -classpath .;jdom.jar ExampleJdomAddWrite.java
java -classpath .;jdom.jar ExampleJdomAddWrite MyXmlFile.xml NewXmlFile.xml Button Title "Mein dritter Button" "Mein neuer Button"
Bezüglich des Kommandozeilenteils '-classpath .;jdom.jar' beachten Sie bitte die Hinweise unter 'JDOM-Voraussetzungen' und '1. JDOM-Programmierbeispiel'.
Falls Ihr Webbrowser die mit "java" beginnende Zeile auf zwei Zeilen umgebrochen hat: Bitte geben Sie diese als eine einzige Kommandozeile ein.
Die Kommandozeilenparameter haben folgende Bedeutung:
Parameter | Beispiel | Bedeutung |
<XmlFile> | MyXmlFile.xml | Diese XML-Datei wird zu Beginn gelesen |
<NewFile> | NewXmlFile.xml | In diese XML-Datei wird das Ergebnis geschrieben (falls die Suchbedingungen erfüllt werden) |
<ParentElem> | Button | Es werden Elemente mit diesem Tag-Namen gesucht |
<Child> | Title | Das gesuchte Element muss ein Child-Element mit diesem Tag-Namen haben |
<FindText> | "Mein dritter Button" | Das Child-Element muss diesen Text als Inhalt haben |
<New> | "Mein neuer Button" | Nur wenn die vorhergehenden Suchbedingungen erfüllt sind, wird ein neues Element mit diesem Child-Element-Inhalt vor das gefundene Element eingefügt |
Mit der Beispiel-XML-Datei 'MyXmlFile.xml' und den angegebenen Beispielparametern wird das dritte <Button>-Element gefunden, da dessen <Title>-Text mit der Suchvorgabe <FindText>="Mein dritter Button" übereinstimmt. Vor dieses <Button>-Element wird ein neues <Button>-Element mit dem angegebenen <Title>-Text <New>="Mein neuer Button" eingefügt. Das Ergebnis wird in die Datei 'NewXmlFile.xml' gespeichert.
// ExampleJdomAddWrite.java import java.util.*; import java.io.*; import org.jdom.*; import org.jdom.input.*; import org.jdom.output.*; public class ExampleJdomAddWrite { public static void main( String[] args ) { if( args.length != 6 ) { System.err.println( "Attention:" ); System.err.println( "jdom.jar must be added to classpath." ); System.err.println( "Usage:" ); System.err.println( "java ExampleJdomAddWrite <XmlFile> <NewFile>" + " <ParentElem> <Child> <FindText> <New>" ); System.err.println( "Example:" ); System.err.println( "java -classpath .;jdom.jar ExampleJdomAddWrite" + " MyXmlFile.xml NewXmlFile.xml Button Title" + " \"Mein dritter Button\" \"Mein neuer Button\"" ); System.exit( 1 ); } try { // ---- Read XML file ---- SAXBuilder builder = new SAXBuilder(); Document doc = builder.build( new File( args[0] ) ); // ---- Modify XML data ---- Element root = doc.getRootElement(); List listParentElements = root.getChildren( args[2] ); // <ParentElem> for( int i=0; i<listParentElements.size(); i++ ) { // Find searched element with given text: Element elMain = (Element)(listParentElements.get( i )); if( null == elMain ) continue; Element elChild = elMain.getChild( args[3] ); // <Child> if( null == elChild ) continue; String s = elChild.getTextTrim(); if( null == s || !s.equals( args[4] ) ) continue; // <FindText> // Add new element at correct position: Element elNew = new Element( args[2] ); // <ParentElem> elNew.addContent( (new Element( args[3] )).addContent( args[5] ) ); listParentElements.add( i, elNew ); // <New> // ---- Write XML file ---- XMLOutputter outp = new XMLOutputter(); outp.setFormat( Format.getPrettyFormat() ); outp.output( doc, new FileOutputStream( new File( args[1] ) ) ); break; // <NewFile> } } catch( Exception ex ) { ex.printStackTrace(); } } }
In einer XML-Datei wird ein bestimmtes Element gesucht, dessen Attribut einen bestimmten Wert hat. Diesem Element wird ein neues Attribut hinzugefügt und das Ergebnis in eine neue XML-Datei gespeichert.
Im selben Verzeichnis, wo sich die oben gezeigte Beispiel-XML-Datei 'MyXmlFile.xml' befindet, speichern Sie den folgenden Java-Sourcecode unter dem Namen 'ExampleJdomAttr.java' und kompilieren und führen ihn aus mit:
javac -classpath .;jdom.jar ExampleJdomAttr.java
java -classpath .;jdom.jar ExampleJdomAttr MyXmlFile.xml NewXmlFile.xml Button size small col blue
Bezüglich des Kommandozeilenteils '-classpath .;jdom.jar' beachten Sie bitte die Hinweise unter 'JDOM-Voraussetzungen' und '1. JDOM-Programmierbeispiel'.
Falls Ihr Webbrowser die mit "java" beginnende Zeile auf zwei Zeilen umgebrochen hat: Bitte geben Sie diese als eine einzige Kommandozeile ein.
Die Kommandozeilenparameter haben folgende Bedeutung:
Parameter | Beispiel | Bedeutung |
<XmlFile> | MyXmlFile.xml | Diese XML-Datei wird zu Beginn gelesen |
<NewFile> | NewXmlFile.xml | In diese XML-Datei wird das Ergebnis geschrieben (falls die Suchbedingungen erfüllt werden) |
<Elem> | Button | Es werden Elemente mit diesem Tag-Namen gesucht |
<AttrS> | size | Das gesuchte Element muss ein Attribut mit diesem Namen haben |
<ValS> | small | Das Attribut muss diesen Wert haben |
<AttrNew> | col | Nur wenn die vorhergehenden Suchbedingungen erfüllt sind, wird ein neues Attribut mit diesem Namen hinzugefügt |
<ValN> | blue | Das neue Attribut erhält diesen Wert |
Mit der Beispiel-XML-Datei 'MyXmlFile.xml' und den angegebenen Beispielparametern wird das zweite <Button>-Element gefunden, da dessen size-Attribut den gesuchten Wert <ValS>="small" hat. Diesem <Button>-Element wird ein neues Attribut mit dem angegebenen Namen <AttrNew>=col und dem Wert <ValN>="blue" hinzugefügt. Das Ergebnis wird in die Datei 'NewXmlFile.xml' gespeichert.
// ExampleJdomAttr.java import java.util.*; import java.io.*; import org.jdom.*; import org.jdom.input.*; import org.jdom.output.*; public class ExampleJdomAttr { public static void main( String[] args ) { if( args.length != 7 ) { System.err.println( "Attention:" ); System.err.println( "jdom.jar must be added to classpath." ); System.err.println( "Usage:" ); System.err.println( "java ExampleJdomAttr <XmlFile> <NewFile>" + " <Elem> <AttrS> <ValS> <AttrNew> <ValN>" ); System.err.println( "Example:" ); System.err.println( "java -classpath .;jdom.jar ExampleJdomAttr" + " MyXmlFile.xml NewXmlFile.xml" + " Button size small col blue" ); System.exit( 1 ); } try { // ---- Read XML file ---- SAXBuilder builder = new SAXBuilder(); Document doc = builder.build( new File( args[0] ) ); // <XmlFile> // ---- Modify XML data ---- Element root = doc.getRootElement(); List listParentElements = root.getChildren( args[2] ); // <Elem> for( int i=0; i<listParentElements.size(); i++ ) { // Find searched element with given attribute: Element elMain = (Element)(listParentElements.get( i )); if( null == elMain ) continue; String s = elMain.getAttributeValue( args[3] ); // <AttrS> if( null == s || !s.equals( args[4] ) ) continue; // <ValS> // Add new attribute to correct element: elMain.setAttribute( args[5], args[6] ); // <AttrNew>=<ValN> // ---- Write result ---- XMLOutputter outp = new XMLOutputter(); outp.setFormat( Format.getPrettyFormat() ); // ---- Show the modified element on the screen ---- System.out.println( "\nModified Element:\n" ); outp.output( elMain, System.out ); System.out.println(); // ---- Write the complete result document to XML file ---- outp.output( doc, new FileOutputStream( new File( args[1] ) ) ); break; // <NewFile> } } catch( Exception ex ) { ex.printStackTrace(); } } }