2008-11-28 7 views
4

Fondamentalement j'ai un petit modèle qui ressemble à:Sélection d'éléments en utilisant la variable

<xsl:template name="templt"> 
    <xsl:param name="filter" /> 
    <xsl:variable name="numOrders" select="count(ORDERS/ORDER[$filter])" /> 
</xsl:template> 

Et je suis en train de l'appeler à l'aide

<xsl:call-template name="templt"> 
    <xsl:with-param name="filter" select="PRICE &lt; 15" /> 
</xsl:call-template> 

Malheureusement, il semble évaluer avant que le modèle est appelé (si effectivement "faux" est passé) En le plaçant entre guillemets fait seulement un littéral de chaîne de sorte que cela ne fonctionne pas non plus. Est-ce que quelqu'un sait si ce que j'essaie de réaliser est possible? Si oui, pourriez-vous nous éclairer? Vive

Répondre

6

comment sur les points suivants:

<?xml version="1.0" encoding="utf-8"?> 
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:output method="xml" indent="yes"/> 

    <xsl:template name="templt"> 
    <xsl:param name="filterNodeName" /> 
    <xsl:param name="filterValue" /> 
    <xsl:variable name="orders" select="ORDERS/ORDER/child::*[name() = $filterNodeName and number(text()) &lt; $filterValue]" /> 
    <xsl:for-each select="$orders"> 
     <xsl:value-of select="."/> 
    </xsl:for-each> 
    </xsl:template> 

    <xsl:template match="/"> 
    <xsl:call-template name="templt"> 
     <xsl:with-param name="filterNodeName" select="'PRICE'" /> 
     <xsl:with-param name="filterValue" select="15" /> 
    </xsl:call-template> 
    </xsl:template> 
</xsl:stylesheet> 

Si vous voulez continuer à utiliser un seul paramètre seulement, vous pouvez tokenizer dans le modèle « templt » abord.

+0

Salutations pour thi s, fonctionne magnifiquement. –

+0

Ross, pour une solution plus générale voir ma réponse. Salutations –

3

Utilisez la bibliothèque EXSLT, en particulier la fonction dyn:evaluate, qui peut évaluer une chaîne en tant qu'expression XPath.

+0

Malheureusement, je n'ai pas la possibilité d'utiliser des bibliothèques supplémentaires pour le moment, mais je vous acclame pour le conseil, ressemble à une fonction utile à connaître –

4

La réponse de Divo est bonne. Toutefois, il limite tout éventuel filtrage à la spécification du nom et de la valeur d'un enfant.

Il est bon de savoir que l'on peut passer une fonction (ce qui revient à a) en tant que paramètre. Ce concept très puissant est implémenté dans FXSL - la bibliothèque de programmation fonctionnelle pour XSLT. FXSL est entièrement écrit en XSLT lui-même. Voici un exemple approprié utilisant the filter function/template. Nous passons le filtre en tant que paramètre à un modèle qui effectue le filtrage. Le filtre peut être n'importe quel code/logique. Dans ce cas particulier, nous transmettons en tant que paramètre une référence à un modèle qui vérifie si un nombre est pair. La transformation complète produit uniquement les éléments "num" dont la valeur est un nombre pair.

Nous pourrions passer très facilement tout autre filtre, en utilisant exactement la même technique: pour filtrer (non) des nombres pairs, les places, les nombres premiers, ... etc.

Prenez note, que l'on doesn Il ne faut pas écrire lui-même le template "filtre" - il est écrit une fois pour toutes et fourni par la bibliothèque FXSL. Par conséquent, vous utilisez généralement la directive < xsl: import /> pour importer le modèle "filtre" et de nombreuses autres fonctions/modèles utiles déjà fournis par FXSL.

La transformation ci-dessous:

 
<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
xmlns:f="http://fxsl.sf.net/" 
xmlns:myIsEven="myIsEven" 
> 

    <xsl:import href="filter.xsl"/> 

    <!-- To be applied on numList.xml --> 

    <xsl:output indent="yes" omit-xml-declaration="yes"/> 

    <myIsEven:myIsEven/> 

    <xsl:template match="/"> 
    <xsl:variable name="vIsEven" 
     select="document('')/*/myIsEven:*[1]"/> 

    Filtering by IsEven: 
    <xsl:call-template name="_filter"> 
     <xsl:with-param name="pList" select="/*/*"/> 
     <xsl:with-param name="pController" select="$vIsEven"/> 
    </xsl:call-template> 

    </xsl:template> 

    <xsl:template name="myIsEven" mode="f:FXSL" 
    match="myIsEven:*"> 
    <xsl:param name="arg1"/> 

    <xsl:if test="$arg1 mod 2 = 0">1</xsl:if> 
    </xsl:template> 
</xsl:stylesheet> 

lorsqu'il est appliqué sur ce document XML source:

 
<nums> 
    <num>01</num> 
    <num>02</num> 
    <num>03</num> 
    <num>04</num> 
    <num>05</num> 
    <num>06</num> 
    <num>07</num> 
    <num>08</num> 
    <num>09</num> 
    <num>10</num> 
</nums> 

produit désiré (filtré) résultat, contenant uniquement les nœuds présentant des valeurs même:

 
Filtering by IsEven: 
<num>02</num> 
<num>04</num> 
<num>06</num> 
<num>08</num> 
<num>10</num> 

Plus d'informations sur la programmation fonctionnelle dans XSLT peut être trouvé sur le page of FXSL et la bibliothèque elle-même peut être téléchargée à partir de sourceforce project.

Pour revenir au problème concret:

Cette transformation:

 
<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
xmlns:f="http://fxsl.sf.net/" 
xmlns:myFilter="myFilter" 
> 

    <xsl:import href="filter.xsl"/> 

    <!-- To be applied on Orders.xml --> 

    <xsl:output indent="yes" omit-xml-declaration="yes"/> 

    <myFilter:myFilter/> 

    <xsl:template match="/"> 
    <xsl:variable name="vFilter" 
     select="document('')/*/myFilter:*[1]"/> 

    Filtering by PRICE < 15: 
    <xsl:call-template name="_filter"> 
     <xsl:with-param name="pList" select="/*/*"/> 
     <xsl:with-param name="pController" select="$vFilter"/> 
    </xsl:call-template> 

    </xsl:template> 

    <xsl:template name="myFilter" mode="f:FXSL" 
    match="myFilter:*"> 
    <xsl:param name="arg1"/> 

    <xsl:if test="$arg1/PRICE &lt; 15">1</xsl:if> 
    </xsl:template> 
</xsl:stylesheet> 

lorsqu'il est appliqué sur ce document XML source:

 
<ORDERS> 
    <ORDER> 
    <PRICE>10</PRICE> 
    </ORDER> 
    <ORDER> 
    <PRICE>7</PRICE> 
    </ORDER> 
    <ORDER> 
     <PRICE>22</PRICE> 
</ORDER> 
    <ORDER> 
     <PRICE>16</PRICE> 
    </ORDER> 
    <ORDER> 
     <PRICE>13</PRICE> 
    </ORDER> 
    <ORDER> 
     <PRICE>19</PRICE> 
    </ORDER> 
</ORDERS> 

produit le résultat recherché:

 
Filtering by PRICE < 15: 
<ORDER> 
    <PRICE>10</PRICE> 
</ORDER> 
<ORDER> 
    <PRICE>7</PRICE> 
</ORDER> 
<ORDER> 
    <PRICE>13</PRICE> 
</ORDER> 
Questions connexes