2008-11-28 3 views
4

В принципе у меня есть небольшой шаблон, который выглядит как:выбор элементов с помощью переменной

<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»). Закрытие его в кавычках делает его строковым литералом, так что он тоже не работает. Кто-нибудь знает, возможно ли то, что я пытаюсь достичь? Если бы вы могли пролить свет на него? Приветствия

ответ

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» первым.

+0

Cheers for thi s, прекрасно работает. – 2008-11-28 11:59:29

+0

Росс, для более общего решения см. Мой ответ. Cheers – 2008-11-29 03:44:32

3

Используйте библиотеку EXSLT, в частности функцию dyn:evaluate, которая может оценивать строку как выражение XPath.

4

Ответ Диво - хороший.

Однако он ограничивает любую возможную фильтрацию указанием имени и значения дочернего элемента.

Хорошо знать, что в качестве параметра можно передать функцию (что составляет a). Эта очень мощная концепция реализована в FXSL - библиотеке функционального программирования для XSLT. FXSL полностью написан в XSLT.

Вот подходящий пример, используя the filter function/template. Мы передаем фильтр в качестве параметра шаблону, который выполняет фильтрацию. Фильтр может быть любым кодом/логикой. В этом конкретном случае мы передаем в качестве параметра ссылку на шаблон, который проверяет, является ли число четным. Полное преобразование выводит только те элементы «num», значение которых равно четному числу.

Мы могли бы легко пройти любой другой фильтр, используя точно такую ​​же технику: для фильтрации (ип) четные числа, квадраты, простые числа, ... и т.д.

ли к сведению, что один Безразлично 't должен написать себе шаблон фильтра' - он написан раз и навсегда и предоставляется библиотекой FXSL. В результате вы обычно используете директиву < xsl: import /> для импорта шаблона «фильтр» и многие другие полезные функции/шаблоны, уже предоставленные 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> 

Дополнительную информацию о функциональном программировании в XSLT можно найти на page of FXSL, а сама библиотека может быть загружена с ее 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> 
Смежные вопросы