对于下面的xml我想在浏览器上从xslt渲染未转义的文本部分,例如:
<one>
<text>
</one>
我希望在浏览器上呈现的标记为:
<text>
但是当我使用下面的应用模板时
<xsl:template match="text()" mode="literalHTML">
<xsl:copy-of select=".">
</xsl:copy-of>
</xsl:template>
以上XML将呈现为:
<text>
如何修改此模板以便打印&amp; lt; text&amp; gt;在浏览器上?
最诚挚的问候, 凯沙夫
答案 0 :(得分:2)
这可以通过非常棘手的递归处理在XSLT 1.0中实现。
幸运的是,可以使用 FXSL (XSLT模板库)在几分钟内解决相同的任务:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:f="http://fxsl.sf.net/"
xmlns:testmap="testmap"
exclude-result-prefixes="xsl f testmap">
<xsl:import href="str-dvc-map.xsl"/>
<testmap:testmap/>
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:template match="/">
<xsl:variable name="vTestMap" select="document('')/*/testmap:*[1]"/>
<xsl:call-template name="str-map">
<xsl:with-param name="pFun" select="$vTestMap"/>
<xsl:with-param name="pStr" select="/*/text()"/>
</xsl:call-template>
</xsl:template>
<xsl:template name="escape" mode="f:FXSL"
match="*[namespace-uri() = 'testmap']">
<xsl:param name="arg1"/>
<xsl:choose>
<xsl:when test="$arg1 = '<'">&lt;</xsl:when>
<xsl:when test="$arg1 = '>'">&gt;</xsl:when>
<xsl:otherwise><xsl:value-of select="$arg1"/></xsl:otherwise>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>
将此转换应用于以下XML文档:
<one>
<text>
</one>
生成了想要的结果:
&lt;text&gt;
,它在浏览器中显示为:<text>
答案 1 :(得分:2)
“棘手的递归处理”
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" omit-xml-declaration="yes"/>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="text()" name="text">
<xsl:param name="text" select="."/>
<xsl:if test="$text != ''">
<xsl:variable name="first" select="substring($text,1,1)"/>
<xsl:choose>
<xsl:when test="$first = '<'">&lt;</xsl:when>
<xsl:when test="$first = '>'">&gt;</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$first"/>
</xsl:otherwise>
</xsl:choose>
<xsl:call-template name="text">
<xsl:with-param name="text" select="substring($text,2,(string-length($text)-1) div 2 + 1)"/>
</xsl:call-template>
<xsl:call-template name="text">
<xsl:with-param name="text" select="substring($text,(string-length($text)-1) div 2 + 3)"/>
</xsl:call-template>
</xsl:if>
</xsl:template>
</xsl:stylesheet>
结果:
<one>
&lt;text&gt;
</one>
编辑:DVC模式以避免溢出。
答案 2 :(得分:0)
我之前也使用递归编写了一个解决方案但我唯一担心的是性能,如果因为这个会有一些内存或一些stackoverflow。我想知道是否有任何解决方案使用&lt; xsl:value-of&gt;或&lt; copy-of&gt;?如果递归可以转换为循环等,请告诉我以下解决方案是否有任何改进。
<xsl:template match="text()" mode="literalHTML">
<xsl:variable name="txt" select="."/>
<xsl:value-of select="smc:escapeChar(smc:escapeChar(smc:escapeChar($txt,'&','&amp;'),'<','&lt;'),'>','&gt;')"/>
</xsl:template>
<xsl:function name="smc:escapeChar">
<xsl:param name="txt"/>
<xsl:param name="char"/>
<xsl:param name="subs"/>
<xsl:result>
<xsl:variable name="result">
<xsl:choose>
<xsl:when test="contains($txt, $char)">
<xsl:variable name="after" select="substring-after($txt,$char)"/>
<xsl:value-of select="substring-before($txt,$char)"/>
<xsl:value-of select="$subs"/>
<xsl:value-of select="smc:escapeChar($after,$char,$subs)"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$txt"/>
</xsl:otherwise>
</xsl:choose>
</xsl:variable>
<xsl:value-of select="$result"></xsl:value-of>
</xsl:result>
</xsl:function>