Создание рекурсивного оператора XSL:If?

Я пытаюсь настроить оператор 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. Я не уверен, как какое-либо из решений поможет в этом.


person Community    schedule 18.06.2009    source источник


Ответы (3)


Вы можете сделать это, используя вложенный предикат для совпадений <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».

person Ben Blank    schedule 18.06.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:

<?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>
person steamer25    schedule 18.06.2009
comment
@steamer25: Вот и все, +1. @dougoftheabaci: Всякий раз, когда вы видите квадратные скобки в XPath, лучше подумать ГДЕ (как в SQL). В этом решении XPath можно перевести как SELECT item FROM container/entry WHERE value ›= 9 AND value ‹= 15. Это операция на основе набора, как и оператор SQL. - person Tomalak; 18.06.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>
person Jay Stevens    schedule 18.06.2009