Сортировка поддерева и сохранение его в переменной xsl: - PullRequest
3 голосов
/ 23 августа 2010

Я работаю с таблицей стилей XSL и пытаюсь использовать показанный здесь метод для хранения отсортированного поддерева в качестве переменной.Я использую saxon 8.7 с xml-maven-plugin для преобразования моего XML-файла.Вот код, который у меня есть:

<xsl:variable name="miniDays">
    <xsl:for-each select="//day[position() > $firstPosToShow]">
        <xsl:sort select="@date" order="descending" />
        <xsl:copy-of select=".|@*" />
    </xsl:for-each>
</xsl:variable>

Когда я запускаю таблицу стилей, я получаю следующую ошибку:

Error at xsl:copy-of on line 598 of file:/D:/home/Projects/src/main/xsl/site.xsl:
  XTDE0420: Cannot create an attribute node (date) whose parent is a document node

Если я просто устанавливаю поддерево переменной без сортировки, оноработает, но не сортируется:

<xsl:variable name="miniDays" select="//day[position() > $firstPosToShow]" />

Если я установил для оператора select-of-select значение ".", он пройдет эту точку, но позже выдает ошибку, когда я на самом деле пытаюсь использоватьпеременные данные.Вот как это используется:

<xsl:for-each select="exsl:node-set($miniDays)">
    <xsl:variable name="in" select="local:calculate-total-in-days(.)" />
    <!-- do some stuff with the var -->
</xsl:for-each>

И ошибка:

Error on line 676 of file:/D:/home/Projects/src/main/xsl/site.xsl:
  XPTY0004: Required item type of first argument of local:calculate-total-in-days() is element(); supplied value has item type document-node()

Функция:

<xsl:function name="local:calculate-total-in-days">
    <xsl:param name="days" as="element()*" />
    <!-- Do some calculations -->
</xsl:function>

Я неправильно использую exsl: node-set?И что должно быть в копии выбора, "."или ". | @ *"?

1 Ответ

1 голос
/ 23 августа 2010

Есть ряд проблем с вашим кодом :

  1. <xsl:for-each select="//day[position() > $firstPosToShow]">.Это выберет каждый элемент day в документе, который находится в позиции $firstPosToShow+1 или больше в наборе day children его родителя !Скорее всего, вы хотите (//day)[position() >= $firstPosToShow]

  2. <xsl:copy-of select=".|@*" />.Это копирует текущий элемент, но также копирует его атрибуты.Атрибут может быть скопирован, только если родительский элемент является элементом.Это не так, поскольку операции внутри нетипизированной переменной создают временное дерево (документ), а узел документа не может иметь атрибутов.Правильная инструкция: <xsl:copy-of select="." />

  3. Элемент списка в следующем коде:

выражение exsl:node-set($miniDays) сноваимеет тип document-node(), а <xsl:for-each> выбирает только один (этот) узел.Это объясняет возникшую ошибку, поскольку local:calculate-total-in-days(.) ожидает элемент-аргумент, но передается узел документа.

Правильный код: :

<xsl:for-each select="exsl:node-set($miniDays)/*"> 
    <xsl:variable name="in" select="local:calculate-total-in-days(.)" /> 
    <!-- do some stuff with the var --> 
</xsl:for-each>

Также,exslt:node:set() не требуется в XSLT 2.0, поскольку в XSLT 2.0 нет типа RTF, и фактически он не поддерживается в Saxon 9.x. Следовательно, правильный код будет :

<xsl:for-each select="$miniDays/*"> 
    <xsl:variable name="in" select="local:calculate-total-in-days(.)" /> 
    <!-- do some stuff with the var --> 
</xsl:for-each>

В качестве альтернативы , вы можете явно указать тип $miniDays как element()*, и это упроститкод - не нужно было бы использовать $miniDays/* - просто $miniDays

...