/*
* XPathW3C.java
* Copyright (C) 2004 Frederic Laurent
* http://www.opikanoba.org
*
* This file is part of the XPath Article.
*
* Lantern is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* Lantern is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with the Xpath article; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
/**
* Test XPath avec l'API du W3C.
* Ce programme est volontairement très simple. Le but n'est pas
* de tester tous les cas possibles et les cas d'erreur mais de
* donner rapidement un aperçu des objets à utiliser.
*
* @author Fréderic Laurent
*/
package test;
import java.io.OutputStreamWriter;
import java.net.URL;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import org.w3c.dom.DOMImplementation;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.xpath.XPathEvaluator;
import org.w3c.dom.xpath.XPathResult;
import org.xml.sax.InputSource;
public class XPathW3C {
// Document DOM sur lequel les requetes XPAth sont effectuées
private Document doc = null;
// Transformateur XSLT
private Transformer out_ser;
/**
* Construction de la classe de test
* - intialisation d'un transfomeur XSLT pour sortir les resultats
* sous forme de fragment de document (la transformation identité
* permet d'avoir le flux XML sur la sortie standard)
*
*/
public XPathW3C() {
try {
this.out_ser = TransformerFactory.newInstance().newTransformer();
this.out_ser.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
} catch (Exception e) {
// si une exception quelconque survient, elle est tracée
// Attention, le traitement est volontairement simple dans un souci
// d'allègement du code ! un traitement correct serait beaucoup plus
// détaillé
System.err.println(e.getMessage());
e.printStackTrace();
}
}
/**
* Ecrit sur la sortie standard n'importe quel noeud XML en utilisant la
* transformation identité si necessaire
*
* @param node noeud à tracer
*/
public void printResult(Node node) {
try {
// test du type de noeud
int nodeType = node.getNodeType();
// s'il s'gait d'un noeud texte, on l'ecrit sur la sortie standard
if (nodeType == Node.CDATA_SECTION_NODE || nodeType == Node.TEXT_NODE) {
System.out.println(node.getNodeValue());
// il se peut que le noeud ait des noeuds voisins, un meme texte
// peut etre représenté par plusieurs noeuds adjacents
Node next = node.getNextSibling();
if (next != null) {
printResult(next);
}
} else {
// sinon on fait appel à la transformation identité
this.out_ser.transform(new DOMSource(node), new StreamResult(
new OutputStreamWriter(System.out)));
}
} catch (Exception e) {
// si une exception quelconque survient, elle est tracée
// Attention, le traitement est volontairement simple dans un souci
// d'allègement du code ! un traitement correct serait beaucoup plus
// détaillé
System.err.println(e.getMessage());
e.printStackTrace();
}
}
/**
* Lecture du document avec JAXP
*
* @param xmlbuf buffer XML
*/
public void loadDocument(String xmlbuf) {
InputSource is;
try {
if (xmlbuf.startsWith("http://") || xmlbuf.startsWith("file:")) {
is = new InputSource(new URL(xmlbuf).toString());
} else {
is = new InputSource(xmlbuf);
}
// lecture du document
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
dbf.setNamespaceAware(true);
dbf.setValidating(false);
this.doc = dbf.newDocumentBuilder().parse(is);
} catch (Exception e) {
// si une exception quelconque survient, elle est tracée
// Attention, le traitement est volontairement simple dans un souci
// d'allègement du code ! un traitement correct serait beaucoup plus
// détaillé
System.err.println(e.getMessage());
e.printStackTrace();
}
}
/**
* Evaluation d'une expression XPath
* - création d'une évaluateur d'expression à partir du
* document DOM
* - parcours de l'ensemble des noeuds résultat et
* affichage de chacun
*
* @param xpath
* expression à évaluer
*/
public void evalXpath(String xpath) {
// création de l'évaluateur : appel explicite à l'API de Xalan
// cette expression va évoluer avec la sortie de la recommandation DOM XPath 3
// et la mise à jour des implementations en conséquence
XPathEvaluator evaluator = new org.apache.xpath.domapi.XPathEvaluatorImpl(doc);
// évaluation de l'expression XPath
XPathResult result = (XPathResult) evaluator.evaluate(xpath, doc, null,
XPathResult.UNORDERED_NODE_ITERATOR_TYPE, null);
// parcours des noeuds correspondant à l'expression XPath
// et affichage de chacun
Node n = result.iterateNext();
while (n != null) {
printResult(n);
n = result.iterateNext();
}
}
/**
* Programme principal
*
* @param args arguments de la ligne de commande
*/
public static void main(String[] args) {
if (args.length < 2) {
System.err.println("usage: java test.XPathW3C xml xpath");
System.err.println(" - xml document XML");
System.err.println(" - xpath expression XPath");
System.exit(1);
}
// Test de l'implementation DOM pour savoir si elle implémente DOM Niveau 3
DOMImplementation impl=null;
try {
// obtention d'une implémentation
impl = DocumentBuilderFactory.newInstance().newDocumentBuilder().getDOMImplementation();
// test de la propriété adéquate
if (!impl.hasFeature("XPath", "3.0")) {
System.err.println("Cette implementation ne supporte pas DOM 3 XPath");
System.exit(1);
} else {
System.out.println("Cette implementation supporte DOM 3 XPath");
}
} catch (Exception e) {
// si une exception quelconque survient, elle est tracée
// Attention, le traitement est volontairement simple dans un souci
// d'allègement du code ! un traitement correct serait beaucoup plus
// détaillé
System.err.println(e.getMessage());
e.printStackTrace();
}
final String uri = args[0];
final String xpath = args[1];
// initialisation de la classe de test
XPathW3C test = new XPathW3C();
// lecture du document
test.loadDocument(uri);
// evaluation de l'expression XPath
test.evalXpath(xpath);
}
}