Question

En gros, j'ai un petit modèle ressemblant à:

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

Et j'essaie de l'appeler en utilisant

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

Malheureusement, il semble qu'il soit évalué avant que le modèle ne soit appelé (si efficacement & "; faux &" est passé). Le mettre entre guillemets en fait seulement un littéral de chaîne, ce qui 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? A la vôtre

Était-ce utile?

La solution

que diriez-vous de ce qui suit:

<?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 souhaitez toujours utiliser un seul paramètre, vous pouvez commencer par définir le gabarit dans le modèle 'templt'.

Autres conseils

La réponse de Divo est bonne.

Toutefois, tout filtrage éventuel est limité à la spécification du nom et de la valeur d'un enfant.

Il est bon de savoir que l'on peut transmettre une fonction (ce qui équivaut à une) en tant que paramètre . Ce concept très puissant est implémenté dans la FXSL , la bibliothèque de programmation fonctionnelle de XSLT. FXSL est entièrement écrit en XSLT lui-même.

Voici un exemple approprié utilisant le filtre fonction / modèle . Nous transmettons 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 passons en paramètre une référence à un modèle qui vérifie si un nombre est pair. La transformation complète génère uniquement les & Quot; num & Quot; éléments dont la valeur est un nombre pair.

Nous pourrions très facilement passer n'importe quel autre filtre , en utilisant exactement la même technique: filtrer des nombres pairs, des carrés, des nombres premiers, etc.

Notez qu'il n'est pas nécessaire d'écrire lui-même le & "filtre &"; modèle : il est écrit une fois pour toutes et est fourni par la bibliothèque FXSL. En conséquence, vous utilisez généralement le & Lt; xsl: import / & Gt; directive pour importer le filtre " " modèle 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é à 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 le résultat souhaité (filtré), contenant uniquement les nœuds avec des valeurs paires:

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

Pour plus d'informations sur la programmation fonctionnelle dans XSLT, consultez la page de FXSL et la bibliothèque elle-même peut être téléchargée à partir de son projet sourceforce .

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é à 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 souhaité:

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

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

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top