XSL: Как лучше сохранить узел в переменной, а затем использовать его в будущих выражениях xpath? - PullRequest
16 голосов
/ 23 декабря 2009

Мне нужно иметь возможность хранить набор узлов в переменной, а затем выполнять дополнительные операции фильтрации / сортировки. Все примеры, которые я видел, включают использование XSL2 или расширений, ни один из которых на самом деле не является опцией.

В моем документе XML есть список отелей, которые можно отсортировать / отфильтровать, а затем пролистать по 5 за раз. Я нахожу, хотя я повторяю много логики, поскольку в настоящее время я не нашел хорошего способа сохранить наборы узлов в переменной xsl, а затем использовать xpath для них для дальнейшей фильтрации / сортировки.

Это то, чего я добиваюсь (извините за код, написанный на макушке, поэтому он может быть не на 100%):

<xsl:variable name="hotels" select="/results/hotels[active='true']" />
<xsl:variable name="3_star_or_less" select="/results/hotels[number(rating) <= 3]" />
<xsl:for-each select="3_star_or_less">
  <xsl:sort select="rating" />
</xsl:for-each>

У кого-нибудь есть пример того, как лучше всего делать подобные вещи?

Ответы [ 3 ]

20 голосов
/ 23 декабря 2009

Попробуйте этот пример:

<xsl:variable name="hotels" select="/results/hotels[active='true']" />
<xsl:variable name="three_star_or_less"
              select="$hotels[number(rating) &lt;= 3]" />
<xsl:for-each select="$three_star_or_less">
    <xsl:sort select="rating" />
    <xsl:value-of select="rating" />
</xsl:for-each>
6 голосов
/ 23 декабря 2009

Нет проблем с сохранением набора узлов в переменной в XSLT 1.0, и расширения не требуются. Если вы просто используете выражение XPath в атрибуте select, равном xsl:variable, то в конечном итоге вы это и сделаете.

Проблема только в том случае, если вы хотите сохранить узлы, которые вы сами сгенерировали в переменной, и даже тогда, только если вы хотите запросить их позже. Проблема здесь в том, что узлы, которые вы выводите, не имеют типа «набор узлов» - вместо этого они являются так называемыми «фрагментами дерева результатов». Вы можете сохранить это в переменной, и вы можете использовать эту переменную для вставки фрагмента в выходные данные (или другую переменную) позже, но вы не можете использовать XPath для запроса по нему. Тогда вам понадобится либо функция EXSLT node-set() (которая преобразует фрагмент дерева результатов в набор узлов), либо XSLT 2.0 (в котором нет фрагментов дерева результатов, только последовательности узлов, независимо от того, откуда они берутся).

Для вашего примера, как указано, это не проблема. Ответ Рубенса дает точный синтаксис.

5 голосов
/ 03 января 2013

Еще одно замечание: если вы хотите использовать переменную как часть оператора XPath, вам нужно выбрать переменную с помощью <xsl:copy-of select="."/> вместо <xsl:value-of select="."/>

value-of будет принимать только текст узла, и вы не сможете использовать функцию набора узлов для возврата чего-либо значимого.

<xsl:variable name="myStringVar">
   <xsl:value-of select="."/>
</xsl:variable>

<!-- This won't work: -->
<Output>
   <xsl:value-of select="node-set($myStringVar)/SubNode" />
</Output>


<xsl:variable name="myNodeSetVar">
   <xsl:copy-of select="."/>
</xsl:variable>

<!-- This will work: -->
<Output>
   <xsl:value-of select="node-set($myNodeSetVar)/SubNode" />
</Output>
...