Создание рекурсивного оператора XSL:If?
-
06-07-2019 - |
Вопрос
Я пытаюсь настроить оператор 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.
[редактировать] Проблема с первыми двумя результатами заключается в том, что они отображают узлы ЭЛЕМЕНТА, то, что я ищу, - возвращать только узлы ввода, у которых есть хотя бы один узел элемента, который соответствует.Я не уверен, как какое-либо из решений помогло бы этому.
Решение
Вы можете выполнить это, используя вложенный предикат в <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(.) >= 9 and number(.) <= 15]]">
<!-- this will loop over <entry>s which contain <item>s within your range -->
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
Выражение будет читаться как "записи, содержащие элементы, значения которых находятся в диапазоне от 9 до 15".
Другие советы
<?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(.) >= 9 and number(.) <= 15]"/>
</xsl:template>
</xsl:stylesheet>
Оператор XPath 'container/entry/item' ссылается на все соответствующие элементы.Предикат [число(.) >= 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(.) >= 9 and number(.) < 15]">
<xsl:value-of select="."/>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
Как насчет этого?...Вы можете делать все, что захотите, внутри цикла 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(.) >= $Param1 and number(.) <= $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>