使用xsl:key函数全局传递参数

时间:2018-07-19 11:01:19

标签: xml xslt

一段时间以来,我一直在使用这个xsl:key。我无法达到期望的输出,而且我也不知道哪里出了错。

以下是xml(XSLT视为xml)的示例:

<xsl:template mode="something" match="node">
    <xsl:variable name="node" select="."/>
    <xsl:variable name="example" select="example"/>
        <xsl:variable name="example" select="normalize-space(.)"/>
        <xsl:if test="not($node//*[matches(local-name(),$example)])">
            <xsl:call-template name="name">
                <xsl:with-param name="rule" select="'S140'"/>
                <xsl:with-param name="other" select="'textValue'"/>
            </xsl:call-template>
        </xsl:if>
</xsl:template>
<xsl:template mode="other" match="node">
    <xsl:call-template name="name">
        <xsl:with-param name="rule" select="'S150'"/>
        <xsl:with-param name="other" select="'textValue'"/>
    </xsl:call-template>
</xsl:template>
<xsl:template mode="another" match="anotherNode">
     <xsl:choose>
        <xsl:when test="something">
            <xsl:variable name="example" select="path"/>
            <xsl:call-template name="name">
                <xsl:with-param name="name" select="'S140'"/>
                <xsl:with-param name="content" select="$example"/>
            </xsl:call-template>
        </xsl:when>
        <xsl:when test="path0">
            <xsl:variable name="example"
                select="path1"/>
            <xsl:call-template name="name">
                <xsl:with-param name="name" select="'S145'"/>
                <xsl:with-param name="content" select="$example"/>
            </xsl:call-template>
        </xsl:when>
        <xsl:when test="path2">
            <xsl:variable name="ele"
                select="path3"/>
            <xsl:call-template name="name">
                <xsl:with-param name="name" select="'S150'"/>
                <xsl:with-param name="content" select="$example"/>
            </xsl:call-template>
        </xsl:when>
</xsl:template>

和我从中读取值的外部XML。

<VALIDATION>
    <VALIDATION_STATE ATTR="S140">a</VALIDATION_STATE>
    <VALIDATION_STATE ATTR="S150">b</VALIDATION_STATE>
    <VALIDATION_STATE ATTR="S155">c</VALIDATION_STATE>
</VALIDATION>

和我的XSLT:

    <xsl:key name="xslRuleCode" match="xsl:call-template[@name = 'name']" use="substring(xsl:with-param[1]/@select,2,4)"/>
    <xsl:param name="validation" select="document('validation.xml')"/>
<xsl:template match="xsl:template">
    <xsl:variable name="xslRule" select="key('xslRuleCode', .)"/>
    <xsl:copy>
        <xsl:apply-templates select="@* | node()"/>
    </xsl:copy>
    <xs:annotation>
        <xs:documentation>Documentation</xs:documentation>
        <attr_id>
            <xsl:value-of select="concat('URL', $xslRule)"/>
        </attr_id>
        <description>
            <xsl:for-each select="$validation/VALIDATION/VALIDATION_STATE">
                <xsl:if test="@ATTR= $xslRule">
                    <xsl:value-of select="node()"/>
                </xsl:if>
            </xsl:for-each>
        </description>
    </xs:annotation>
</xsl:template>

在XML文件中(以XSLT格式)有两个值,另一个在外部XML文件中。

我们的想法是接触这两个元素,将它们进行比较,如果匹配,则将元素的值写入相关注释中。

预期输出为:

<xsl:template mode="something" match="node">
    <xsl:variable name="node" select="."/>
    <xsl:variable name="example" select="example"/>
        <xsl:variable name="example" select="normalize-space(.)"/>
        <xsl:if test="not($node//*[matches(local-name(),$example)])">
            <xsl:call-template name="name">
                <xsl:with-param name="rule" select="'S140'"/>
                <xsl:with-param name="other" select="'textValue'"/>
            </xsl:call-template>
        </xsl:if>
</xsl:template>
 <xs:annotation>
        <xs:documentation>Documentation</xs:documentation>
        <attr_id>
            URL/S140
        </attr_id>
        <description>
            a
        </description>
<xsl:template mode="other" match="node">
    <xsl:call-template name="name">
        <xsl:with-param name="rule" select="'S150'"/>
        <xsl:with-param name="other" select="'textValue'"/>
    </xsl:call-template>
</xsl:template>
<xs:annotation>
        <xs:documentation>Documentation</xs:documentation>
        <attr_id>
            URL/S150
        </attr_id>
        <description>
            b
        </description>

另一项编辑:

如果我与<xsl:call-template>匹配而不是在<xsl:template>中匹配 我能够达到我想要的价值。但是我不想在调用模板之后创建注释,它必须在每个模板之后。

<xsl:template match="xsl:call-template[@name = 'name']">
    <xsl:param name="xslRule" select="substring(xsl:with-param[1]/@select, 2, 4)"/>
    <xsl:copy>
        <xsl:apply-templates select="@* | node()"/>
    </xsl:copy>
    <xsl:choose>
        <xsl:when test="ancestor::xsl:template/last()">
            <xs:annotation>
                <xs:documentation>documentation</xs:documentation>
                <rule_id>
                    <xsl:value-of select="concat('URL', $xslRule)"/>
                </rule_id>
                <description>
                    <xsl:for-each select="$validation/VALIDATION/VALIDATION_STATE">
                <xsl:if test="@ATTR= $xslRule">
                    <xsl:value-of select="node()"/>
                </xsl:if>
            </xsl:for-each>
                </description>
            </xs:annotation>
        </xsl:when>
    </xsl:choose>
</xsl:template>

1 个答案:

答案 0 :(得分:1)

我认为您不需要在这里使用xsl:key。仅当您匹配命名模板并想要获得所有xsl:call-templates称为它的东西时,您才需要这样做。

我认为只需执行此操作即可解决您的问题...

<xsl:variable name="xslRule" 
              select="substring((.//xsl:call-template/xsl:with-param[@name='rule'])[1]/@select, 2, 4)"/>

这假设每个模板中只有一个xsl:call-template

编辑:如果模板中有多个xsl:call-template语句,并且想要在主模板本身之后为每个语句添加注释,则可以使用xsl:for-each

<xsl:template match="xsl:template">
    <xsl:copy>
        <xsl:apply-templates select="@* | node()"/>
    </xsl:copy>
    <xsl:for-each select=".//xsl:call-template/xsl:with-param[1]/@select">
        <xsl:variable name="xslRule" select="." />
        <xs:annotation>
            <xs:documentation>Documentation</xs:documentation>
            <attr_id>
                <xsl:value-of select="concat('URL', $xslRule)"/>
            </attr_id>
            <description>
                <xsl:for-each select="$validation/VALIDATION/VALIDATION_STATE">
                    <xsl:if test="@ATTR= $xslRule">
                        <xsl:value-of select="node()"/>
                    </xsl:if>
                </xsl:for-each>
            </description>
        </xs:annotation>
    </xsl:for-each>
</xsl:template>