我相信这应该适用于在 XSLT 1.0 中转义 XML:
<xsl:template match="*" mode="escape">
<xsl:variable name="currentNode" select="." />
<xsl:value-of select="concat('<', name(.))"/>
<xsl:apply-templates select="@*" mode="escape"/>
<xsl:for-each select="namespace::*[name() != 'xml'][not(. = $currentNode/../namespace::*)]">
<xsl:call-template name="EscapeNamespace">
<xsl:with-param name="namespace" select="." />
</xsl:call-template>
</xsl:for-each>
<xsl:value-of select="'>'"/>
<xsl:apply-templates select="node()" mode="escape" />
<xsl:value-of select="concat('</', local-name(.), '>')"/>
</xsl:template>
<xsl:template match="@*" mode="escape">
<xsl:value-of select="concat(' ', name(.), '="')"/>
<xsl:call-template name="EscapeText">
<xsl:with-param name="text" select="." />
</xsl:call-template>
<xsl:value-of select="'"'"/>
</xsl:template>
<xsl:template match="text()" mode="escape">
<xsl:call-template name="EscapeText">
<xsl:with-param name="text" select="." />
</xsl:call-template>
</xsl:template>
<xsl:template name="EscapeNamespace">
<xsl:param name="namespace" />
<xsl:variable name="prefix">
<xsl:choose>
<xsl:when test="name($namespace) = ''">
<xsl:value-of select="'xmlns'"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="concat('xmlns:',name($namespace))" />
</xsl:otherwise>
</xsl:choose>
</xsl:variable>
<xsl:value-of select="concat(' ', $prefix, '="')"/>
<xsl:call-template name="EscapeText">
<xsl:with-param name="text" select="$namespace" />
</xsl:call-template>
<xsl:value-of select="'"'"/>
</xsl:template>
<xsl:variable name="EntitiesRaw">
<entity value=""" escaped="&quot;" />
<entity value="&" escaped="&amp;" />
<entity value="<" escaped="&lt;" />
<entity value=">" escaped="&gt;" />
<entity value="'" escaped="&apos;" />
</xsl:variable>
<xsl:variable name="Entities" select="msxsl:node-set($EntitiesRaw)" />
<xsl:template name="EscapeText">
<xsl:param name="text" />
<xsl:variable name="foundEntity" select="$Entities/entity[contains($text, @value)]" />
<xsl:choose>
<xsl:when test="$foundEntity">
<xsl:call-template name="EscapeText">
<xsl:with-param name="text" select="substring-before($text, $foundEntity/@value)" />
</xsl:call-template>
<xsl:value-of select="$foundEntity/@escaped" />
<xsl:call-template name="EscapeText">
<xsl:with-param name="text" select="substring-after($text, $foundEntity/@value)" />
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$text"/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
您只需在变量中构建要转义的 XML,然后通过模板运行它:
<xsl:template match="something">
<requestXml>
<xsl:variable name="requestXml">
<ISD_XMLGateway>
<Entity><xsl:value-of select="2 + 5" /></Entity>
<Origin>5 < 6 and 7 > 2</Origin>
<xsl:apply-templates select="otherStuff" />
<ElementWithAttributes a="10" b="12" />
</ISD_XMLGateway>
</xsl:variable>
<xsl:apply-templates select="msxsl:node-set($requestXml)" mode="escape" />
</requestXml>
</xsl:template>
上面在两个地方使用了 msxsl:node-set(),但我相信大多数非 MS XSL 引擎都有该功能的等价物。