Thursday, August 21, 2008

requête XPath en java

Une solution simple (à mon goût) existe pour récupérer une valeur ou un attribut dans un fichier Xml en java sans avoir à le parcourir complètement avec Sax ou avec Dom.

Voici un petit exemple de mise en œuvre des APIS XPATH de java 1.5 s'appuyant sur Sax :

Voici le fichier XML source :
<?xml version="1.0" encoding="ISO-8859-1"?>
<level1>
<level2 level2-attribute1="valueOfLevel2-attribute1">
<level3 level3-attribute1="valueOfLevel3-attribute1">
<level41>valueOfLevel41</level41>
<level42>valueOfLevel42</level42>
</level3>
</level2>
</level1>
le code "technique" :

...
import java.io.InputStream;
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;
import org.xml.sax.InputSource;

...

public static String executeXpath(InputStream sourceXml, String xPathQuery)
throws XPathExpressionException {

// creation de la source sax
InputSource source = new InputSource(sourceXml);

// creation de la requete XPTAH
XPathFactory xPathFactory = XPathFactory.newInstance();
XPath xpath = xPathFactory.newXPath();
XPathExpression xPathExpression = xpath.compile(xPathQuery);

/* execution de la requete xPath sur le fichier XML */
String resultat = (String) xPathExpression.evaluate(source,
XPathConstants.STRING);

return resultat;

}
...
}
La mise en œuvre :

public static void main(String[] args) {

try {
/* recuperation du flux xml */

InputStream xml = null;
String result = null;
String xPathQuery = null;

/* exemple 1 */
xml = Main.class.getResourceAsStream("/fichier.xml");
xPathQuery = "/level1/level2/@level2-attribute1";
result = XpathHelper.executeXpath(xml, xPathQuery);

System.out.println("xpathQuery : " + xPathQuery
+ "---> resultat : " + result);

/* exemple 2 */
xml = Main.class.getResourceAsStream("/fichier.xml");
xPathQuery = "/level1/level2/level3/level41";
result = XpathHelper.executeXpath(xml, xPathQuery);

System.out.println("xpathQuery : " + xPathQuery
+ "---> resultat : " + result);
} catch (XPathExpressionException e) {
e.printStackTrace();
}

}


Le résultat en console :
xpathQuery : /level1/level2/@level2-attribute1---> resultat : valueOfLevel2-attribute1
xpathQuery : /level1/level2/level3/level41---> resultat : valueOfLevel41


Le tout a le mérite d'être assez simple, élégant et performant.

3 comments:

jey350 said...

J'ai mis en ligne sur mon blog, une classe java de gestion des requêtes Xpath avec mise en cache des expressions XPath compilées, pour récupérer le source c'est cette adresse: http://www.devbypractice.com/cache-de-requete-xpath-java/

Anonymous said...

Cela ne semble pas fonctionner avec un namespace particulier.

Exemple si dan sle fichier xml on a

blabla

la requete

*[dc:title] ne fonctionnera pas.


Une idée ?

Jérémy Sevellec said...

Tout à fait exact, si tu utilises un namespace, il faut mettre en place une classe de type NameSpaceContext comme documenté ici : http://xml.apache.org/xalan-j/xpath_apis.html#namespacecontext