XSLT将特定节点下的xml块转换为该节点的xml转义内容

时间:2015-03-10 13:06:27

标签: xslt escaping xslt-2.0 cdata

如何解决以下问题的任何想法都将受到高度赞赏。

INPUT:

<p>
    <div>
     Original<br/>This is the original <b>acid</b>, a hydroxy monocarboxylic <span class="hl1">acid</span>.
    </div>
</p>

期望的输出:

<p>
    <div>
     Original&lt;br/&gt;This is the original &lt;b&gt;acid&lt;/b&gt;, a hydroxy monocarboxylic &lt;span class=&quot;hl1&quot;&gt;acid&lt;/span&gt;.
    </div>
</p>

尝试1:

`<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" >
<xsl:output omit-xml-declaration="yes" indent="no" encoding="UTF-8"/>
<!--The identity template -->
<xsl:template match="node()|@*">
    <xsl:copy>
        <xsl:apply-templates select="node()|@*"/>
    </xsl:copy>
</xsl:template>

<xsl:template match="div">
    <xsl:copy>
            <xsl:value-of select="/" disable-output-escaping="no"/>
    </xsl:copy>
</xsl:template>

`

ATTEMPT2: 作为替代方案,我想到将子元素的内容放入CDATA包装器中。

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" >
<xsl:output omit-xml-declaration="yes" indent="no" encoding="UTF-8"/>
<!--The identity template -->
<xsl:template match="node()|@*">
    <xsl:copy>
        <xsl:apply-templates select="node()|@*"/>
    </xsl:copy>
</xsl:template>

<xsl:template match="div">
    <xsl:copy>
            <xsl:text disable-output-escaping="yes">&lt;![CDATA[</xsl:text>
            <xsl:value-of select="/" />
            <xsl:text disable-output-escaping="yes">]]&gt;</xsl:text>
    </xsl:copy>
</xsl:template>

但那不能给我我想要的东西。 谁有更好的主意?我正在使用XSLT 2.0

2 个答案:

答案 0 :(得分:1)

以下是使用Saxon 9.6 HE,PE和EE支持的XSLT 3.0 serialize()的建议:

<xsl:stylesheet version="3.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:xs="http://www.w3.org/2001/XMLSchema"
  exclude-result-prefixes="xs">

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

<xsl:template match="div">
  <xsl:copy>
    <xsl:apply-templates mode="serialize"/>
  </xsl:copy>
</xsl:template>

<xsl:template match="node()" mode="serialize">
  <xsl:variable name="ser-params">
    <output:serialization-parameters xmlns:output="http://www.w3.org/2010/xslt-xquery-serialization">
      <output:omit-xml-declaration value="yes"/>
    </output:serialization-parameters>
  </xsl:variable>
  <xsl:value-of select="serialize(., $ser-params/*)"/>
</xsl:template>

</xsl:stylesheet>

使用旧版Saxon 9,你可以使用扩展功能serialize,如http://xsltransform.net/pPqsHTx所示:

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

<xsl:output name="inline" omit-xml-declaration="yes"/>

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

<xsl:template match="div">
  <xsl:copy>
    <xsl:apply-templates mode="serialize"/>
  </xsl:copy>
</xsl:template>

<xsl:template match="node()" mode="serialize">

  <xsl:value-of xmlns:saxon="http://saxon.sf.net/" select="saxon:serialize(., 'inline')"/>
</xsl:template>

</xsl:stylesheet>

答案 1 :(得分:0)

如果您将xsl:value-of更改为xsl:copy-of并调整select,则第二次尝试应该有效:

<xsl:template match="div">
    <xsl:copy>
        <xsl:text disable-output-escaping="yes">&lt;![CDATA[</xsl:text>
        <xsl:copy-of select="node()" />
        <xsl:text disable-output-escaping="yes">]]&gt;</xsl:text>
    </xsl:copy>
</xsl:template>