【问题标题】:Sorting a subtree and storing it in an xsl:variable对子树进行排序并将其存储在 xsl:variable 中
【发布时间】:2010-08-23 01:49:20
【问题描述】:

我正在使用 XSL 样式表,并尝试使用 here 所示的方法将已排序的子树存储为变量。我正在使用 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]" />

如果我将 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?什么应该在副本的选择中,“。”还是“.|@*”?

【问题讨论】:

  • 向我们展示足够多的输入 XML 以了解发生了什么。
  • 好问题 (+1)。有关代码中问题的详尽讨论以及每个问题的解决方案,请参阅我的答案。

标签: xml xslt saxon


【解决方案1】:

您的代码存在许多问题

  1. &lt;xsl:for-each select="//day[position() &gt; $firstPosToShow]"&gt; 。这将选择文档中的每个day 元素,该元素位于$firstPosToShow+1day 子集其父代 中的更大位置!很可能你想要(//day)[position() &gt;= $firstPosToShow]

  2. &lt;xsl:copy-of select=".|@*" /&gt; 。这会复制当前元素,但也会复制其属性。只有当父元素是元素时,才能复制属性。情况并非如此,因为无类型变量内部的操作会创建临时树(文档),并且文档节点不能具有属性。正确的指令是:&lt;xsl:copy-of select="." /&gt;

  3. 列表项如下代码:

表达式exsl:node-set($miniDays) 又是document-node() 类型,而&lt;xsl:for-each&gt; 只选择一个(这个)节点。这解释了引发的错误,因为 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/*——只需@987654338 @

【讨论】:

    猜你喜欢
    • 2019-04-01
    • 1970-01-01
    • 1970-01-01
    • 2016-03-24
    • 1970-01-01
    • 2014-11-19
    • 2022-11-22
    • 2016-09-11
    • 1970-01-01
    相关资源
    最近更新 更多