首页 > 解决方案 > XSLT 通过将原始值传递给模板来修改 EXACT 元素的属性值

问题描述

我正在努力让这个名为 XSLT 的可憎之物工作。我需要在 EXACT 路径中获取 EXACT 属性,将其原始值传递给模板,然后用模板的结果重写该值。

我有这样的文件:

<?xml version="1.0" encoding="windows-1251"?>
<File>
  <Document ReportYear="17">
        ...
        ...
  </Document>
</File>

所以我做了一个这样的 XSLT:

<?xml version="1.0" encoding="windows-1251"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl">

    <xsl:output method="xml" encoding="windows-1251" indent="yes" />

    <xsl:template match="@* | node()">
        <xsl:copy>
            <xsl:apply-templates select="@* | node()" />
        </xsl:copy>
    </xsl:template>

    <xsl:template name="formatYear">
        <xsl:param name="year" />
        <xsl:value-of select="$year + 2000" />
    </xsl:template>

    <xsl:template match="File/Document">
        <xsl:copy>
            <xsl:apply-templates select="@*" />
            <xsl:attribute name="ReportYear">
                <xsl:call-template name="formatYear">
                    <xsl:with-param name="year" select="@ReportYear" />
                </xsl:call-template>
            </xsl:attribute>
        </xsl:copy>
        <xsl:apply-templates />
    </xsl:template>

</xsl:stylesheet>

这工作正常,除了它立即关闭<Document>标签并将其内容立即放在其自身之后。

另外,我可以在ReportYear不重复两次的情况下解决属性值吗?我试过current()了,但没有用。

标签: xsltxslt-1.0

解决方案


如果您<xsl:copy>在将模板应用于 的剩余内容之前关闭<Document>,那么当然<Document>会在 的剩余内容<Document>出现在输出中之前关闭。

<xsl:stylesheet version="1.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:msxsl="urn:schemas-microsoft-com:xslt"
    exclude-result-prefixes="msxsl"
>
    <xsl:output method="xml" encoding="windows-1251" indent="yes" />

    <xsl:template match="@* | node()">
        <xsl:copy>
            <xsl:apply-templates select="@* | node()" />
        </xsl:copy>
    </xsl:template>

    <xsl:template match="Document">
        <xsl:copy>
            <xsl:apply-templates select="@*" />
            <xsl:attribute name="ReportYear">
                <xsl:value-of select="@ReportYear + 2000" />
            </xsl:attribute>
            <xsl:apply-templates select="node()" />
        </xsl:copy>
    </xsl:template>

</xsl:stylesheet>

输出

<?xml version="1.0" encoding="windows-1251"?>
<File>
  <Document ReportYear="2017">
        ...
        ...
  </Document>
</File>

我认为不需要仅用于添加 2000 的额外模板@ReportYear。但如果你必须,你可以像这样简化整个事情

<xsl:template name="formatYear">
    <xsl:param name="year" select="@ReportYear" />   <!-- you can define a default value -->
    <xsl:value-of select="$year + 2000" />
</xsl:template>

<xsl:attribute name="ReportYear">
    <xsl:call-template name="formatYear" />  <!-- ...and can use it implicitly here -->
</xsl:attribute>

推荐阅读