如何借助XSLT来浏览XML字符?

时间:2010-03-17 14:44:14

标签: xml xslt

我需要借助于XSLT转换从XML节点内部转换XML字符。我有<text>&lt;&gt;and other possible characters</text>,当我将它放在body标签内时,需要将其作为有效的格式化HTML。

4 个答案:

答案 0 :(得分:37)

<xsl:template match="text">
  <body>
    <xsl:value-of select="." disable-output-escaping="yes" />
  </body>
</xsl:template>

请注意,输出不再保证是格式良好的XML。

答案 1 :(得分:3)

使用xslt 2.0,我想出了这个。请注意,输出不能保证是正确的xml,简单的不等式会使输出变得混乱。

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">

<xsl:character-map name="a">
    <xsl:output-character character="&lt;" string="&lt;"/>
    <xsl:output-character character="&gt;" string="&gt;"/>
</xsl:character-map>

<xsl:output use-character-maps="a"/>

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

</xsl:stylesheet>

答案 2 :(得分:1)

我还没有找到这个问题的答案。所以我得出的结论是,这是无法做到的。我找到了这个问题的解决方法,在服务器端unescaping文件。

答案 3 :(得分:0)

另一种解决方案。这个不使用xml后处理器,因此很容易用作进一步xslt处理的输入。还保证创建有效的xml。 这是一个xslt 2.0解决方案,在“文档”标签中转义文本,使用saxon进行测试。 您应该修改“allowedtags”变量以定义您自己的数据模型。直接的孩子是标签,他们下面的标签是可能的属性。 从xsd读取允许的标签留作读者的练习(请与我分享)。

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:fn="http://www.w3.org/2005/xpath-functions"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    xmlns:my="http://magwas.rulez.org/my"
>
<xsl:output method="xml" version="1.0" encoding="utf-8" indent="yes"/>

<xsl:variable name="allowedtags">
<li/>
<ul/>
<br/>
<a><href/></a>
</xsl:variable>

<xsl:template match="@*|*|processing-instruction()|comment()" mode="unescape">
    <xsl:copy>
        <xsl:apply-templates select="*|@*|text()|processing-instruction()|comment()" mode="unescape"/>
    </xsl:copy>
</xsl:template>

<xsl:template match="documentation" mode="unescape">
    <documentation>
    <xsl:call-template name="doc">
        <xsl:with-param name="str">
            <xsl:value-of select="."/>
        </xsl:with-param>
    </xsl:call-template>
    </documentation>
</xsl:template>

<xsl:template name="doc">
    <xsl:param name="str"/>
    <xsl:variable name="start" select="fn:substring-before($str,'&lt;')"/>
    <xsl:variable name="rest" select="fn:substring-after($str,'&lt;')"/>
    <xsl:variable name="fulltag" select="fn:substring-before($rest,'&gt;')"/>
    <xsl:variable name="tagparts" select="fn:tokenize($fulltag,'[  &#xA;]')"/>
    <xsl:variable name="tag" select="$tagparts[1]"/>
    <xsl:variable name="aftertag" select="fn:substring-after($rest,'&gt;')"/>
    <xsl:variable name="intag" select="fn:substring-before($aftertag,fn:concat(fn:concat('&lt;/',$tag),'&gt;'))"/>
    <xsl:variable name="afterall" select="fn:substring-after($aftertag,fn:concat(fn:concat('&lt;/',$tag),'&gt;'))"/>
    <xsl:value-of select="$start"/>
    <xsl:choose>
    <xsl:when test="$tag">
        <xsl:variable name="currtag" select="$allowedtags/*[$tag = local-name()]"/>
        <xsl:if test="$currtag">
            <xsl:element name="{$currtag/local-name()}">
                <xsl:for-each select="$tagparts[position()>1]">
                    <xsl:variable name="anstring" select="fn:replace(.,'^([^ &#xA;=]*)=.*$','$1')"/>
                    <xsl:variable name="antag" select="$currtag/*[$anstring = local-name()]"/>
                    <xsl:if test="$antag">
                        <xsl:attribute name="{$antag/local-name()}">
                            <xsl:value-of select="fn:replace(.,'^.*[^ &#34;]*&#34;([^&#34;]*)&#34;.*','$1')"/>
                        </xsl:attribute>
                    </xsl:if>
                </xsl:for-each>
                <xsl:if test="$intag">
                    <xsl:call-template name="doc">
                        <xsl:with-param name="str">
                            <xsl:value-of select="$intag"/>
                        </xsl:with-param>
                    </xsl:call-template>
                </xsl:if>
            </xsl:element>
        </xsl:if>
        <xsl:if test="$afterall">
            <xsl:call-template name="doc">
                <xsl:with-param name="str">
                    <xsl:value-of select="$afterall"/>
                </xsl:with-param>
            </xsl:call-template>
        </xsl:if>
    </xsl:when>
    <xsl:otherwise>
                    <xsl:value-of select="$str"/>
    </xsl:otherwise>
    </xsl:choose>
</xsl:template>

</xsl:stylesheet>