XSLT 2.0:将位置作为模板参数

时间:2016-11-07 17:41:16

标签: xml xslt xslt-2.0

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

  

XPTY0020:子轴的上下文项的必需项类型是   节点()

<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>

1 个答案:

答案 0 :(得分:2)

您只需使用

即可
<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>

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

相关问题