Сортировка exsl: node-set. Вернуть узел по этому положению - PullRequest
2 голосов
/ 18 марта 2010

У меня есть набор узлов

<menuList>
  <mode name="aasdf"/>
  <mode name="vfssdd"/>
  <mode name="aswer"/>
  <mode name="ddffe"/>
  <mode name="ffrthjhj"/>
  <mode name="dfdf"/>
  <mode name="vbdg"/>
  <mode name="wewer"/>
  <mode name="mkiiu"/>
  <mode name="yhtyh"/>
  and so on...
</menuList>

Теперь он отсортирован таким образом

 <xsl:variable name="rtf">
    <xsl:for-each select="//menuList/mode">
       <xsl:sort data-type="text" order="ascending" select="@name"/>
          <xsl:value-of select="@name"/>
    </xsl:for-each>
 </xsl:variable>

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

<xsl:value-of select="exsl:node-set($rtf)[position() = 3]"/>

и получаю ошибку ответа.Как мне это сделать?

Ответы [ 2 ]

4 голосов
/ 18 марта 2010

В предоставленном коде есть как минимум две ошибки:

  1. <xsl:value-of select="@name"/>

Если существует более одного смежного текстового узла, они объединяются в один. В результате RTF имеет только один (длинный) одиночный текстовый узел, а третий узел отсутствует.

2. <xsl:value-of select="exsl:node-set($rtf)[position() = 3]"/>

При этом запрашивается третий узел, содержащийся в exsl:node-set($rtf), однако exsl:node-set($rtf) является узлом документа временного дерева, созданного функцией расширения exsl:node-set() - это только один узел. Поэтому вышеприведенное выражение XPath вообще ничего не выделяет.

Одним из правильных решений является следующее :

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 xmlns:msxsl="urn:schemas-microsoft-com:xslt"
 >

 <xsl:template match="/">
    <xsl:variable name="rtf">
        <xsl:for-each select="//menuList/mode">
           <xsl:sort data-type="text" order="ascending" select="@name"/>
              <xsl:copy-of select="."/>
        </xsl:for-each>
     </xsl:variable>
    <xsl:value-of select="msxsl:node-set($rtf)/*[position()=3]/@name"/>
 </xsl:template>
</xsl:stylesheet>
2 голосов
/ 18 марта 2010

Вы используете <xsl:value-of> в своей переменной. Это не копирует узел, но его строковое значение (значение атрибута @name узла). Это означает, что вы создаете переменную, содержащую каскадную строку, но не имеющую структуры.

Попробуйте:

<xsl:variable name="rtf">
  <xsl:for-each select="//menuList/mode">
    <xsl:sort select="@name" data-type="text" order="ascending" />
    <xsl:copy-of select="."/>
  </xsl:for-each>
</xsl:variable>

Теперь ваша переменная содержит фрагмент дерева результатов, состоящий из <mode> узлов в выбранном вами порядке, что означает, что это:

<xsl:value-of select="exsl:node-set($rtf)/*[3]/@name" />
<!-- don't forget you have element nodes now! ^^^^^^ -->

будет работать. Также обратите внимание, что …/*[position() = 3] и …/*[3] - это одно и то же.

...