Ответ Диво хороший.
Однако любая возможная фильтрация ограничивается указанием имени и значения дочернего элемента.
Хорошо знать, что можно передать (что равно a) функцию в качестве параметра . Эта очень мощная концепция реализована в FXSL - библиотеке функционального программирования для XSLT. FXSL полностью написан на самом XSLT.
Вот соответствующий пример использования функции фильтра / шаблона . Мы передаем фильтр в качестве параметра шаблону, который выполняет фильтрацию. Фильтр может быть любым кодом / логикой. В этом конкретном случае мы передаем в качестве параметра ссылку на шаблон, который проверяет, является ли число четным. Полное преобразование выводит только те «num» элементы, значение которых является четным числом.
Мы могли бы очень легко пропустить любой другой фильтр , используя точно такую же технику: фильтровать (не) четные числа, квадраты, простые числа, ... и т. Д.
Обратите внимание, что самому шаблону «фильтра» не нужно писать - он пишется раз и навсегда и предоставляется библиотекой FXSL. В результате вы обычно просто используете директиву для импорта шаблона «filter» и многих других полезных функций / шаблонов, уже предоставленных 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 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 < 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>