使用XSLT转义XML正在跳过命名空间

时间:2017-08-10 15:07:52

标签: xml xslt

我有一个XSLT文档,用于将一个XML文档转换为另一个XML文档。部分转换需要一些输入XML,将其转义(例如<mytag someattribute="value"/>转换为&lt;mytag someattribute=\"value\"/&gt;),然后将其插入到输出XML文档中。

我遇到的问题是,如果标记指定了命名空间,它会在转义过程中跳过命名空间。

我正在使用System.Xml.Xsl.XslCompiledTransform在.NET应用程序(Framework 4.0)中执行转换以执行转换。 (它只支持XSLT 1.0)。

我的模板

<xsl:template match="*" mode="serialize">
    <xsl:text>&lt;</xsl:text>
    <xsl:value-of select="name()"/>
    <xsl:apply-templates select="@*" mode="serialize" />
    <xsl:choose>
        <xsl:when test="node()">
            <xsl:text>&gt;</xsl:text>
            <xsl:apply-templates mode="serialize" />
            <xsl:text>&lt;/</xsl:text>
            <xsl:value-of select="name()"/>
            <xsl:text>&gt;</xsl:text>
        </xsl:when>
        <xsl:otherwise>
            <xsl:text> /&gt;</xsl:text>
        </xsl:otherwise>
    </xsl:choose>
</xsl:template>

<xsl:template match="@*" mode="serialize">
    <xsl:text> </xsl:text>
    <xsl:value-of select="name()"/>
    <xsl:text>=\"</xsl:text>
    <xsl:value-of select="."/>
    <xsl:text>\"</xsl:text>
</xsl:template>

<xsl:template match="text()" mode="serialize">
    <xsl:value-of select="."/>
</xsl:template>

示例输入XML

<link xmlns:xlink="http://www.w3.org/1999/xlink" 
    action="goto" xlink:href="http://localhost"/>

预期产出

&ltlink xmlns:xlink=\"http://www.w3.org/1999/xlink\" action=\"goto\" xlink:href=\"http://localhost\"/&gt;

实际输出

&ltlink action=\"goto\" xlink:href=\"http://localhost\"/&gt;

如何更改模板以便输出命名空间?

1 个答案:

答案 0 :(得分:0)

使用@ MartinHonnen的建议我发现我可以稍微修改现有的XSLT以解决问题。我添加了一个新模板,以应用于我试图逃避的XML的根标记(我本可以修改现有的match="*"模板,但我会在所有标记上获取命名空间)处理命名空间:

<xsl:template match="myroottag" mode="serialize">
    <xsl:text>&lt;</xsl:text>
    <xsl:value-of select="name()"/>
    <xsl:text> </xsl:text>
    <!-- This for-each adds the namespaces -->
    <xsl:for-each select="namespace::*">
        <xsl:text> xmlns:</xsl:text>
        <xsl:value-of select="name()"/>
        <xsl:text>=\"</xsl:text>
        <xsl:value-of select="."/>
        <xsl:text>\" </xsl:text>
    </xsl:for-each>
    <xsl:apply-templates select="@*" mode="serialize" />
    <xsl:choose>
        <xsl:when test="node()">
            <xsl:text>&gt;</xsl:text>
            <xsl:apply-templates mode="serialize" />
            <xsl:text>&lt;/</xsl:text>
            <xsl:value-of select="name()"/>
            <xsl:text>&gt;</xsl:text>
        </xsl:when>
        <xsl:otherwise>
            <xsl:text> /&gt;</xsl:text>
        </xsl:otherwise>
    </xsl:choose>
</xsl:template>