使用变量选择元素

时间:2008-11-28 10:52:39

标签: xml xslt fxsl

基本上我有一个小模板,如下所示:

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

我试图用

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

不幸的是,它似乎在调用模板之前对其进行评估(因此传入有效的“false”)将其括在引号中只会使它成为字符串文字,因此也不起作用。有人知道我想要实现的目标是否可行?如果是这样,你能否对它有所了解?干杯

3 个答案:

答案 0 :(得分:6)

以下内容如何:

<?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>

如果您仍然只想使用单个参数,则可以首先在模板'templt'中进行标记。

答案 1 :(得分:4)

Divo的答案很好。

但是,它会将任何最终过滤限制为指定子项的名称和值。

很高兴知道一个人可以传递一个(多于一个)函数作为参数。这个非常强大的概念在FXSL - XSLT的功能编程库中实现。 FXSL完全用XSLT编写。

以下是使用the filter function/template的相应示例。我们将过滤器作为参数传递给执行过滤的模板。过滤器可以是任何代码/逻辑。在这种特殊情况下,我们将参数作为参数传递给模板,该模板检查数字是否为偶数。完整转换仅输出那些“num”元素,其值为偶数。

我们可以使用完全相同的技术轻松传递任何其他过滤器:过滤(联合)偶数,正方形,素数等......

请注意,一个人不必自己编写“过滤器”模板 - 它一次性写入并由FXSL库提供。因此,您通常只使用&lt; xsl:import /&gt;指令导入“过滤器”模板和FXSL已经提供的许多其他有用的功能/模板。

以下转型:

<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>

应用于此源XML文档时:

<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>

生成所需(已过滤)的结果,仅包含具有偶数值的节点:

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

可以在page of FXSL上找到有关XSLT中的函数编程的更多信息,并且可以从其sourceforce project下载库本身。

回到具体问题:

这种转变:

<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>

应用于此源XML文档时:

<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>  

产生想要的结果:

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

答案 2 :(得分:3)

使用EXSLT库,特别是dyn:evaluate函数,它可以将字符串计算为XPath表达式。