В основном у меня есть небольшой шаблон, который выглядит так:
<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 < 15" />
</xsl:call-template>
К сожалению, кажется, что он оценивает его до вызова шаблона (так что фактически передается «false») Заключение его в кавычки делает его только строковым литералом, так что это тоже не работает. Кто-нибудь знает, возможно ли то, что я пытаюсь достичь? Если так, не могли бы вы пролить на это свет? Ваше здоровье





как насчет следующего:
<?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()) < $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.
Используйте библиотеку EXSLT, в частности функцию dyn: оценить, которая может оценивать строку как выражение XPath.
К сожалению, на данный момент у меня нет возможности использовать дополнительные библиотеки, но приветствую совет, похоже, полезная функция, о которой нужно знать.
Ответ Диво хороший.
Однако он ограничивает любую возможную фильтрацию указанием имени и значения дочернего элемента.
Полезно знать, что можно передать функцию (что составляет) в качестве параметра. Эта очень мощная концепция реализована в FXSL - библиотеке функционального программирования для XSLT. FXSL полностью написан на XSLT.
Вот подходящий пример с использованием функция / шаблон фильтра. Мы передаем фильтр как параметр в шаблон, который выполняет фильтрацию. Фильтр может быть любым кодом / логикой. В этом конкретном случае мы передаем в качестве параметра ссылку на шаблон, который проверяет, является ли число четным. Полное преобразование выводит только те элементы "num", значение которых является четным числом.
Мы могли бы легко пропустить любой другой фильтр, используя ту же технику: фильтровать (не) четные числа, квадраты, простые числа и т. д.
Обратите внимание, что не обязательно самому писать шаблон "фильтра". - он пишется раз и навсегда и предоставляется библиотекой 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 можно найти в страница FXSL, а саму библиотеку можно загрузить из проект sourceforce.
Чтобы вернуться к конкретной проблеме:
Это преобразование:
<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 < 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>
Росс, более общее решение см. В моем ответе. Ваше здоровье