XSL : Former une expression xPATH dynamiquement

17-05-2013
Laurent Bientz

Nous avons vu dans un article précédent comment former le nom d'un noeud XML dynamiquement, nous allons voir dans ce billet comment former une expression xPATH dynamiquement.

Pour illustrer l'explication, nous allons nous baser sur un flux XML à N niveaux matérialisant une arborescence de dossiers de type TreeView :

<?xml version="1.0" encoding="UTF-8"?>
<root>
    <View>
        <dirs>
            <dir>
                <name>var</name>
                <dirs>
                    <dir>
                        <name>lib</name>
                        <dirs>
                            <dir>
                                <name>apt</name>
                                <!-- ... -->
                            </dir>
                        </dirs>
                    </dir>
                    <div>
                        <name>log</name>
                        <dirs>
                            <dir>
                                <name>apache2</name>
                                <!-- ... -->
                            </dir>
                        </dirs>
                    </div>
                </dirs>
            </dir>
            <dir>
                <name>home</name>
                <!-- ... -->
            </dir>
        </dirs>
    </View>
</root>

En XSL, on aimerait pouvoir for-eacher comme en PHP avec un while readdir, ce n'est hélas nativement pas possible. On ne peut pas former un xPATH dynamiquement car ce n'est pas une string. Cependant un nouveau XMLNS permet de compenser ce manque :

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:php="http://php.net/xsl" xmlns="http://www.w3.org/1999/xhtml" xmlns:dyn="http://exslt.org/dynamic" extension-element-prefixes="dyn">

Par la suite, nous pouvons former une expression xPATH dynamiquement à l'aide du prefixe dyn:evaluate.

Nous pouvons donc imaginer un select couplé à l'aide d'un template récursif pour réaliser le traitement :

<select name="directory_id" id="directory_id" size="2">
    <option value="0" selected="selected">Répertoire</option>
    <xsl:call-template name="RecursiveDirsSelect">
        <xsl:with-param name="path">dirs/dir</xsl:with-param>
    </xsl:call-template>
</select>
<xsl:template name="RecursiveDirsSelect">
    <xsl:param name="path" />                
    <xsl:for-each select="dyn:evaluate(concat('//View/', $path))">
        <xsl:variable name="position" select="position()" />
        <option><xsl:value-of select="name" /></option>
        <xsl:if test="count(dirs/dir) > 0">
            <xsl:call-template name="RecursiveDirsSelect">
                <xsl:with-param name="path"><xsl:value-of select="concat($path,'[',$position,']/dirs/dir')" /></xsl:with-param>                    
            </xsl:call-template>
        </xsl:if>
    </xsl:for-each>
</xsl:template>

 

Drake - 2013-10-09 08:52:50
Is there any chance that XProc will be surptpoed? I think it's great that we can now get rid of the DOM boilerplate code, but there is still the code to prepare, execute and examine results of an XSLT or XPath or XQuery.This still leaves the door open for imperative pollution in XML applications.I have been a user of Apache Cocoon for a long time, and its pipelines do away completely with all the Java boilerplate, making XML applications completely declarative. XProc is supposed to do the same thing.

Apporter votre contribution

Expérience utilisateur

Wandi vous propose de découvrir une nouvelle approche de la navigation sur un site web...
Êtes-vous prêt ?

Démarrer l'expérience