XSLT 2.0:将位置作为模板参数传递时出现项目类型错误

XSLT 2.0: Item type error when passing position as template parameter

我一直在努力尽可能地简化代码。由于 XML 的性质,我无法共享原始代码,我不得不清理代码,只留下让我头疼的片段。我不想为每个月创建一个离散的行,而是只想调用相同的代码 12 次。这节省了 space(在 20k+ 行中我需要所有我可以使用的 space)并且当代码需要调整时它也简化了事情(最近似乎每季度发生一次)。但是,当我使用以下内容时出现错误:

XPTY0020: Required item type of the context item for the child axis is node()

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:template match="/">
        <xsl:for-each select="contract">
            <xsl:for-each select="1 to 12">
                <xsl:call-template name="monthPayments">
                    <xsl:with-param name="month" select="position()"/>
                </xsl:call-template>
            </xsl:for-each>
        </xsl:for-each>
    </xsl:template>
    <xsl:template name="monthPayments">
        <xsl:param name="month"/>
        <!-- Month is the position of the for-each loop from 1 to 12 -->
        <xsl:value-of select="payments[plannedPaymentDate/@month = $month]/@amount"/>
    </xsl:template>
</xsl:stylesheet>

我已经搜索并发现了几个有此错误的问题,但答案没有意义。我认为问题在于具有原子值的上下文节点。某些人的解决方案似乎是声明一个上下文变量。但是,我只是不确定为什么我在这里需要它,因为我在一个 for-each 中,它为模板提供上下文和被调用模板中的值。至少如果我没有将 position() 作为参数传递,它会这样做。

我已经将 for-each x-t​​o-y 用于其他函数而没有问题,但这是我第一次将位置作为模板的参数传递。

任何关于如何简化我的代码片段的想法都会很棒。我只是不知道如何克服错误!

编辑:

该片段不是一个很好的例子。对不起!我需要它在我为每个月创建一个单元格的 SpreadsheetML 下工作。所以它看起来更像下面,显然前面有很多样式之类的代码:

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:template match="/">
        <xsl:for-each select="contracts/ES_CMContract">
            <xsl:for-each select="1 to 12">
                <Cell ss:StyleID="s87">
                    <!-- Monthly Payments -->
                    <Data ss:Type="Number">
                        <xsl:call-template name="monthPayments">
                            <xsl:with-param name="month" select="position()"/>
                        </xsl:call-template>
                    </Data>
                </Cell>
            </xsl:for-each>
        </xsl:for-each>
    </xsl:template>
    <xsl:template name="monthPayments">
        <xsl:param name="month"/>
        <!-- Month is the position of the for-each loop from 1 to 12 -->
        <xsl:value-of select="payments/ES_CM2Payment[plannedPaymentDate/ESP_DATE/@month = $month]/amount/ES_COSTOBJECT/co_costprice/ESP_COSTPRICE/@anglosaxon_amount"/>
    </xsl:template>
</xsl:stylesheet>

您可以简单地使用

<xsl:template match="/">
  <xsl:value-of select="for $month in 1 to 12 return contract/payments[plannedPaymentDate/@month = $month]/@amount"/>
</xsl:template>

甚至

<xsl:template match="/">
  <xsl:value-of select="contract/payments[plannedPaymentDate/@month = (1 to 12)]/@amount"/>
</xsl:template>

虽然这可能会给出不同的值顺序。

至于需要为每个数字创建一个XML元素,使用

<xsl:template match="/">
    <xsl:for-each select="contracts/ES_CMContract">
        <xsl:variable name="contract" select="."/>
        <xsl:for-each select="1 to 12">
            <Cell ss:StyleID="s87">
                <!-- Monthly Payments -->
                <Data ss:Type="String">
                    <xsl:value-of select="$contract/payments/ES_CM2Payment[plannedPaymentDate/ESP_DATE/@month = current()]/amount/ES_COSTOBJECT/co_costprice/ESP_COSTPRICE/@anglosaxon_amount"/>
                </Data>
            </Cell>
        </xsl:for-each>
    </xsl:for-each>
</xsl:template>

如果您确实需要调用模板,请确保将我显示的外部变量作为第二个参数传递。