Создание рекурсивного XSL: оператора If? - PullRequest
2 голосов
/ 18 июня 2009

Я пытаюсь настроить оператор XSL: IF, который отображает только записи с узлом, который находится между двумя значениями. Достаточно просто, верно? Это просто если больше чем и если меньше чем. Проблема в том, что вместо того, чтобы тестировать его на одном узле, мне нужно протестировать его до 52.

Допустим, у меня есть какой-то XML, который выглядит следующим образом:

<container>
    <entry>
        <item>1</item>
        <item>2</item>
        <item>3</item>
        <item>4</item>
        <item>5</item>
        <item>6</item>
        <item>7</item>
        <item>8</item>
        <item>9</item>
        <item>10</item>
    </entry>
</container>

Теперь скажите, что мне дали диапазон 9–15. Поскольку некоторые из узлов попадают в этот диапазон, я хочу отобразить эту запись. Но если бы мне дали диапазон 11–15, ни один из узлов не подходил, поэтому я бы не хотел, чтобы он отображался.

Проблема в том, что ... я абсолютно не представляю, как вы это сделаете. Я знаю, что вы можете указать одно значение, но я не могу придумать простой способ проверить каждый узел.

Кстати, все это делается в последнем стабильном выпуске Symphony CMS.

[править] Проблема с первыми двумя результатами состоит в том, что они отображают узлы ITEM. Я ищу только те узлы ENTRY, у которых есть хотя бы один совпадающий узел ITEM. Я не уверен, как любое из решений могло бы помочь этому.

Ответы [ 3 ]

2 голосов
/ 19 июня 2009

Это можно сделать с помощью вложенного предиката в совпадениях <entry>:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
    <xsl:template match="/">
        <xsl:for-each select="container/entry[item[number(.) &gt;= 9 and number(.) &lt;= 15]]">
            <!-- this will loop over <entry>s which contain <item>s within your range -->
        </xsl:for-each>
    </xsl:template>
</xsl:stylesheet>

Выражение будет читаться как «записи, содержащие элементы, значения которых находятся в диапазоне от 9 до 15».

2 голосов
/ 18 июня 2009
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
    <xsl:template match="/">
        <xsl:copy-of select="container/entry/item[number(.) &gt;= 9 and number(.) &lt;= 15]"/>
    </xsl:template>
</xsl:stylesheet>

Оператор XPath «контейнер / запись / элемент» относится ко всем соответствующим элементам. Предикат [число (.)> = 9 и число (.) <= 15] сокращает этот список. Некоторые операции XSLT (например, xsl: value-of) имеют подразумеваемый фильтр, который захватывает только первое значение. В этих случаях вы можете использовать xsl: for-each: </p>

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
    <xsl:template match="/">
        <xsl:for-each select="container/entry/item[number(.) &gt;= 9 and number(.) &lt; 15]">
            <xsl:value-of select="."/>
        </xsl:for-each>
    </xsl:template>
</xsl:stylesheet>
1 голос
/ 18 июня 2009

Как насчет этого .... Вы можете делать все, что захотите, внутри цикла for-each или просто взять набор узлов, возвращенный в переменной, и использовать его где-нибудь еще.

   <?xml version='1.0'?>
    <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:template match="/">
        <!-- Your first param -->
        <xsl:param name="Param1" select="4"/>
        <!-- Your second param -->
        <xsl:param name="Param2" select="9"/>
            <xsl:variable name="ResultNodeSet">
                <xsl:for-each select="/container/entry/item[number(.) &gt;= $Param1 and number(.) &lt;= $Param2]">
                  <!-- What ever else you want to do can go here-->
                  <xsl:copy-of select="."/>
                </xsl:for-each>
            </xsl:variable>  
        <xsl:value-of select="$ResultNodeSet"/>
    </xsl:template> 
    </xsl:stylesheet>
...