对子树进行排序并将其存储在xsl:变量中

时间:2010-08-23 01:49:21

标签: xml xslt saxon

我正在使用XSL样式表,我正在尝试使用显示here的方法将已排序的子树存储为变量。我正在使用xx-maven-plugin的saxon 8.7来转换我的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]" />

如果我将copy-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 个答案:

答案 0 :(得分:1)

您的代码存在许多问题

  1. <xsl:for-each select="//day[position() > $firstPosToShow]">。这将选择文档中位于day的每个$firstPosToShow+1元素,或者在其父的day集合中更大的(//day)[position() >= $firstPosToShow]元素!很可能你想要<xsl:copy-of select=".|@*" />

  2. <xsl:copy-of select="." />。这会复制当前元素,但也会复制其属性。仅当父元素是元素时,才能复制属性。情况并非如此,因为无类型变量中的操作会创建临时树(文档),而文档节点不能具有属性。正确的说明是:exsl:node-set($miniDays)

  3. 列表项目在以下代码中:

               

  4. 表达式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中不需要<xsl:for-each select="$miniDays/*"> <xsl:variable name="in" select="local:calculate-total-in-days(.)" /> <!-- do some stuff with the var --> </xsl:for-each> ,因为XSLT 2.0中没有RTF类型,事实上Saxon 9.x不支持。 因此,正确的代码将是

    $miniDays

    或者,您可以考虑将element()*的类型明确指定为$miniDays/*,这样可以简化代码 - 没有必要使用{{1} } - 只是$miniDays