Advanced   Java   Services DOM   XPath Back Next Up Home


DOM  XPath

Durch das in Java 1.5 eingeführte Package javax.xml.xpath wird der Zugriff auf den DOM-Baum drastisch vereinfacht. Da eine XML-Datei den gleichen Regeln folgt wie ein Dateisystem liegt die Einführung eines Pfadkonzepts nahe. Wir vereinfachen unser letztes Beispiel mit Hilfe der Möglichkeiten, die Java 1.5 bereitgestellt hat. Mit einem XPath kann man z. Bsp. direkt auf die Daten zugreifen.





Zugriff auf die Textdaten

Anlegen einer Instanz von XPath

import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathFactory;

XPathFactory xPathFactory = XPathFactory.newInstance();
XPath xPath = xPathFactory.newXPath();

Einen XPath durch den Baum zu den gewünschten Daten bereitstellen.

String titelTextPath = "buecher/buch/titel/text()"; // Pfad zum text von <titel> 

Der Pfad verwendet an seinem Ende die Funktion text(), die jede XPath-Implementierung u.a. realisieren muß. Die Funktion holt den Text des einen ChildElements von <titel>. Siehe auch die unten folgende Tabelle.

Den Pfad übergibt man der Methode compile. Diese Methode liefert eine Instanz vom Typ XPathExpression. Falls der übergebene Pfad nicht existiert oder ein Syntaxfehler vorliegt wird eine XPathExpressionException geworfen.

import javax.xml.xpath.XPathExpression;
import javax.xml.xpath.XPathExpressionException;

XPathExpression xPathExpression = xPath.compile(titelTextPath); // XPathExpressionException

Wird keine Exception geworfen, kann man das Ergebnis abholen. Da es mehrere titel-Einträge gibt ist eine Liste zu erwarten. Für diesen Fall gibt es die Konstante XPathConstants.NODESET, die wie folgt eingesetzt wird:

NodeList result = (NodeList)expr.evaluate(doc, XPathConstants.NODESET);

evaluate() arbeitet nicht generisch, es muß gecastet werden.


Das vollständige Beispiel

import java.io.File;
import java.io.IOException;

import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathExpression;
import javax.xml.xpath.XPathExpressionException;
import javax.xml.xpath.XPathFactory;

/**
 * Titel ausgeben mit XPath
 */
private static void beispiel1()
{
   try
   {
      DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
      DocumentBuilder dBuilder = dbFactory.newDocumentBuilder(); // ParserConfigurationException
      File xmlFile = new File("buecher.xml");
      Document doc = dBuilder.parse(xmlFile); // SAXException, IOException
      doc.getDocumentElement().normalize();
      // com.sun.org.apache.xerces.internal.dom.DeferredDocumentImpl

      XPathFactory xPathFactory = XPathFactory.newInstance();
      XPath xPath = xPathFactory.newXPath();
      String titelTextPath = "buecher/buch/titel/text()"; // Pfad zum text von 
      // Liefert eine NodeList von TextNodes
      XPathExpression expr = xPath.compile(titelTextPath); // XPathExpressionException

      NodeList result = (NodeList)expr.evaluate(doc, XPathConstants.NODESET);
      //Object result = expr.evaluate(doc, XPathConstants.NODESET);
      NodeList titelTextNodes = (NodeList) result;
      // com.sun.org.apache.xml.internal.dtm.ref.DTMNodeList

      for (int i = 0; i < titelTextNodes.getLength(); i++)
      {
         Node node = titelTextNodes.item(i);
         System.out.println(node.getNodeValue());
      }
   }
   catch (ParserConfigurationException | SAXException | IOException | XPathExpressionException ex)
   {
      ex.printStackTrace();
   }
}

Output

Deutschland, ein Wintermaerchen
Der Untertan
Erfolg

Mit dieser Idee läßt sich auch der komplette Baum leicht ausgeben.

String vornameTextPath = "buecher/buch/autor/vorname/text()";   // Pfad zum text von <vorname>
String nachnameTextPath = "buecher/buch/autor/nachname/text()";   // Pfad zum text von <nachname>
String isbnTextPath = "buecher/buch/isbn/text()";   // Pfad zum text von <isbn>

Wie oben kann man so mehrere org.w3c.dom.NodeList erhalten und auswerten.





Achtzehn XPath Beispiele und was Sie liefern

Eine Zusammenstellung von achtzehn Pfadvarianten von einfach bis raffiniert und was man damit finden kann. Sie beziehen sich alle auf die Datei "buecher.xml".

XPath als String Wirkung
"" TransformerException: Leerer Ausdruck.
"/" Liefert das Document.
"/buecher/buch" Liefert alle buch-Elemente (hier 3).
"/buecher/buch[isbn]" Liefert alle buch-Elemente die ein ChildElement namens isbn haben, hier also alle.
"/buecher/buch/isbn" Liefert alle isbn-Elemente.
"/buecher/buch/isbn/text()" text() ist eine Funktion, die das TextChild liefert. Hier wird also zu jedem isbn-Element das TextChild geliefert. Vorsicht: Textchilds können Zeilenumbrüche und Tabs enthalten, die durch die Formatierung der xml-Datei entstehen.
"/buecher/buch/text()" Liefert zu allen buch-Elementen alle TextChilds, hier also 12 TextChilds, macht 4 TextChilds pro buch-Element.
"/buecher/buch/autor/text()" Liefert zu allen autor-Elementen alle TextChilds, hier also 9 TextChilds, macht 3 TextChilds pro autor-Element.
"/buecher/buch[@type='paperback']" Liefert alle buch-Elemente, die das angegebene Attribut mit Namen type und dem Wert 'paperback' haben, hier also 2.
"/buecher/buch[@type='paperback']/titel/text()" Liefert die TextChilds aller titel-Elemente aller buch-Elemente, die das angegebene Attribut haben, hier also 2.
"/buecher/buch/isbn[@type='13']/text()" Liefert die Textchilds (ISBN-Nummer) aller isbn-Elemente zu allen buch-Elementen mit dem isbn-Attribut type='13'.
"/buecher/buch[2]/titel/text()" Liefert das TextChild zu allen titel-Elementen des zweiten buch-Elements, Zählung beginnt bei 1.
"/buecher/buch/autor/*" Liefert alle Elementchilds von allen autor-Elementen, liefert keine TextChilds!
"/buecher/buch/autor/node()"Die node()-Funktion liefert alle Childs von allen autor-Elementen, also auch die TextChilds.
"/buecher/buch[@*]" Liefert alle drei buch-Elemente, weil jedes buch-Element ein Atrribut hat.
"/buecher/buch/autor[@*]" Liefert eine leere NodeList, weil kein autor-Element (irgend)ein Attribut hat.
"/buecher/buch/autor[vorname='Heinrich']/nachname/text()" Liefert alle nachnamen-Elementen, die vornamen-Elemente mit dem TextChild "Heinrich" haben.
"/buecher/buch[isbn[@type='10']]/titel/text()" Sucht alle buch-Elemente, die ein isbn-Attribut mit type='10' haben und liefert von diesen buch-Elementen die TextChilds der titel-Elemente.








Valid XHTML 1.0 Strict top Back Next Up Home