Fiches / Articles

Cadre Fonctionnel

Utilisation de XSL (eXtensible Stylesheet Langugage)

Cadre Technique

Xalan, Tomcat

Identifiant 

SYS_XSL _01

Référent technique 


Version 

1.0

Auteur 

Alexandre Brillant

Date

04/01

Source

http://www.w3c.org, documentation de xalan

Dépendance

SYS_SERVLET_01

XSL (eXtensible Stylesheet Language) est un langage issu de la technologie XML (eXtensible Markup Language) visant à transformer un document XML vers un autre document (HTML par exemple). Il est composé d'une partie XSLT (eXtensible Stylesheet Language Transformation) contenant des directives de transformations et d'un sous-langage Xpath fournissant des moyens s'accès vers des éléments XML.

XSL est adapté :

Exemple de fichier à transformer :


<?xml version="1.0" encoding="ISO-8859-1"?>

<!-- Exemple de fichier XML -->

<catalogue name="2001">

<element name="portable1">
<description>
 Portable comprenant les services XXX
</description>

<abonnement name="XX" duree="10" total="100"/>
<abonnement name="XX" duree="20" total="180"/>
<hors_abonnement unite="5"/>
</element>

<element name="portables2">

<description>

 Portable comprenant les services XXX2

</description>

<abonnement name="XX" duree="10" total="200"/>
<abonnement name="XX" duree="20" total="380"/>
<hors_abonnement unite="4"/>
</element>

</catalogue>

Cet exemple contient une description sommaire de formules d'abonnement.

Exemple de fichier XSL :



<?xml version="1.0" encoding="ISO-8859-1"?>

<!-- Exemple d'affichage du contenu de 'catalogue.xml' -->

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0">

<xsl:param name="version" select="'alpha'"/>

<!-- Traiter le premier élément contenant catalogue
-->

<xsl:template match="//catalogue">


<html>

<body bgcolor="#ffffff">

<h1>

Présentation du catalogue <xsl:value-of select="@name"/>

</h1>

<hr/>

<table border="1">

<xsl:for-each select="element">

<tr>

<td>

<xsl:value-of select="@name"/>

</td>

<td>

<xsl:value-of select="./description"/>

</td>

<td>

<xsl:apply-templates select="abonnement"/>

</td>

<td>

<xsl:value-of select="hors_abonnement/@unite"/> 

</td>

</tr>

</xsl:for-each>

</table>

<hr/>

Version <xsl:value-of select="$version"/>

</body>

</html>

</xsl:template>

<!-- Traiter les différents types d'abonnement -->

<xsl:template match="abonnement">

<b>

<xsl:value-of select="@name"/> :

</b>

<xsl:value-of select="@duree"/> Min,

<xsl:value-of select="@total"/> Francs

<xsl:if test="position()!=last()">

<p></p>

</xsl:if>

<p/>

</xsl:template>

</xsl:stylesheet>

Ce fichier transforme le document précédent en une page HTML contenant une tableau récapitulatif. Il intègre aussi la notion de paramètre passée par un programme (xsl:param).

Deux langages sont présents dans XSL, le premier est XSLT et le second est le langage final (HTML dans cet exemple). XSLT fonctionne par des sauts dans le document grâce à la balise xsl:template. Les critères du saut sont définis grâce à la norme Xpath. Par exemple chemin1/chemin2 signifie trouver tous les éléments chemin2 contenus dans chemin1.

L'API xalan (http://xml.apache.org) est très simple à utiliser pour appliquer XSL. Le cœur étant l'utilisation d'une instance de XSLTProcessor obtenue par une "factory" XSLTProcessorFactory. La méthode process est appliquée avec un objet représentant les données XML, un autre contenant le fichier XSL et enfin un objet représentant le fichier résultat.

La définition d'une source XML est associée à la classe XSLTInputSource. Une instance peut être initialisée avec un path, un flux ou même un arbre DOM. Dans ce dernier cas, il faut initialiser l'instance XSLTProcessor avec une instance de org.apache.xalan.xpath.xdom.XercesLiaison.

L'interface ProblemListener peut être utilisée avec la classe XSLTProcessor pour traiter les erreurs.

Exemple de programme java :


package hexadev;

import org.apache.xalan.xslt.*;
import org.apache.xalan.xpath.xml.*;
import org.w3c.dom.Node;

/**
 * Exemple de transformation XSL avec un paramètre version
 */

public class TestXSL1 {

    /**
     * Affichage des messages d'erreur */
    static class CustomProblemListener implements ProblemListener {

	public boolean message( java.lang.String msg ) { return true; }

	public boolean problem( short where, 
			        short classification, 
			        Object styleNode, 
			        Node sourceNode, 
				String msg, 
				String id, 
				int lineNo, 
				int charOffset) {

	    System.err.println( "Message : " + msg + " Line :
" + lineNo );

	    return true;
	}
    }

    public static void main( String[] args ) {

	try {

	    XSLTProcessor processor = XSLTProcessorFactory.getProcessor();

	    processor.setProblemListener( new CustomProblemListener() );

	    // Paramètre
	    processor.setStylesheetParam( "version", "'1.0'"
);

	    // Sources XML et XSL
	    XSLTInputSource xml = new XSLTInputSource( "catalogue.xml"
);

	    XSLTInputSource xsl = new XSLTInputSource( "catalogue.xsl"
);

	    // Résultat
	    XSLTResultTarget result = new XSLTResultTarget( "catalogue.htm"
);

	    // Transformation
	    processor.process( xml, xsl, result );

	} catch( Exception ex ) {
	    System.err.println( ex.getMessage() );
	}

    }
}

Exemple de servlet java :

Pour augmenter les performances, il est possible de "compiler" le fichier xsl grâce à la méthode processStylesheet de la classe XSLTProcessor. On obtient un objet StylesheetRoot qui réalise la transformation grâce à la méthode process.

Dans exemple montre aussi comment passer les paramètres de l'URL ou d'un formulaire au moteur de transformation.


package hexadev;

import javax.servlet.*;
import javax.servlet.http.*;
import java.util.Enumeration;
import java.io.*;

import org.apache.xalan.xslt.*;
import org.apache.xalan.xpath.xml.*;
import org.w3c.dom.Node;

/**
 * Exemple de servlet retournant le résultat
 * d'une transformation XSL en réponse 
 */

public class TestXSLServlet extends HttpServlet {

    // Préparation de la transformation

    public void init( ServletConfig config ) throws ServletException {
	super.init( config );

	try {
	    processor = XSLTProcessorFactory.getProcessor();
	    FileInputStream input = new FileInputStream(
config.getInitParameter( "xsl" ) );
	    style = processor.processStylesheet( new XSLTInputSource( input
) );
	    XMLFile = config.getInitParameter( "xml" );
	} catch( Exception ex ) {
	    ex.printStackTrace();
	    throw new ServletException( ex.getMessage() );
	}
    }

    // Transformation avec passage des paramètres de la
requête

    public void doGet( HttpServletRequest request,
HttpServletResponse response ) throws ServletException, IOException {

	try {

	    // Passage des paramètres au moteur de transformation

	    for ( Enumeration enum = request.getParameterNames();
enum.hasMoreElements() ; ) {
		String _param = (String)enum.nextElement();
		processor.setStylesheetParam( _param, "'" +
request.getParameter( _param ) + "'" );

	    }

	    response.setContentType( "text/html" );

	    style.process( processor, 
			   new XSLTInputSource( new FileInputStream( XMLFile ) ), 
			   new XSLTResultTarget( response.getWriter() ) );

	} catch( Exception ex ) {
	    throw new ServletException( ex.getMessage() );
	}
    }

    private XSLTProcessor processor;
    private StylesheetRoot style;
    private String XMLFile;

}

Exemple de descripteur web.xml :

Deux paramètres xml et xsl sont utilisés pour indiquer où trouver les fichiers de données et de transformation XSL.



<!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web
Application 2.2//EN"
"http://java.sun.com/j2ee/dtds/web-app_2_2.dtd">

<web-app>

    <display-name>hexadevServlet</display-name>

    <description>

    Exemple de servlet

    </description>

    <servlet>

        <servlet-name>hexadev</servlet-name>

        <servlet-class>hexadev.TestXSLServlet</servlet-class>

       <init-param>

            <param-name>xsl</param-name>
           
<param-value>d:\temp\test-xalan\catalogue.xsl</param-value>

        </init-param>

        <init-param>

            <param-name>xml<param-name>
           
<param-value>d:\temp\test-xalan\catalogue.xml</param-value>

        </init-param>

    </servlet>

</web-app>