2014-02-17 67 views
1

輸入XML是這樣的:解析文本是在XSLT選擇的節點

<input> 
    <foo>John&apos;s bar</foo> 
    <bar>test</bar> 
    <foobar>testing</foobar> 
</input> 

XSL改造後:

<input> 
    <foo>John's bar</foo> 
    <bar>this_test</bar> 
</input> 

但遺留系統要求:

<foo>John&apos;s bar</foo> 

<foo>John's bar</foo>

所以我希望保留<foo>的值,而不是讓XSLT解析它。

我嘗試使用<xsl:output method="text"/>但沒有運氣成功的..

我覺得XML在加載時被解析和XSLT只是作爲輸出是... 如果這是真的,我ATLEAST想逃離它,使&apos;本身無關在輸入XML中是&apose還是'。我試過

XSLT是這樣的:

<?xml version="1.0" encoding="UTF-8"?> 
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:fo="http://www.w3.org/1999/XSL/Format"> 
<xsl:output method="xml"/> 

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

回答

1

如果僅限於XSLT 1.0,使用disable-output-escaping="yes"。此屬性可用於xsl:textxsl:value-of元素,在XSLT 2.0中不推薦使用此屬性。

樣式(XSLT 1.0)

<?xml version="1.0" encoding="UTF-8"?> 

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 

    <xsl:output method="xml" indent="yes"/> 
    <xsl:strip-space elements="*"/> 

    <xsl:variable name="vApos">'</xsl:variable> 
    <xsl:variable name="vAmp">&amp;</xsl:variable> 

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

    <xsl:template match="bar"> 
     <xsl:copy> 
      <xsl:text>this_</xsl:text> 
      <xsl:apply-templates/> 
     </xsl:copy> 
    </xsl:template> 

    <xsl:template match="foobar"/> 

    <xsl:template match="foo"> 
     <xsl:variable name="rep"> 
     <xsl:call-template name="replace-string"> 
      <xsl:with-param name="text" select="."/> 
      <xsl:with-param name="replace" select="$vApos" /> 
      <xsl:with-param name="with" select="concat($vAmp,'apos;')"/> 
     </xsl:call-template> 
     </xsl:variable> 
     <xsl:copy> 
     <xsl:value-of select="$rep" disable-output-escaping="yes"/> 
     </xsl:copy> 
    </xsl:template> 

    <xsl:template name="replace-string"> 
    <xsl:param name="text"/> 
    <xsl:param name="replace"/> 
    <xsl:param name="with"/> 
    <xsl:choose> 
     <xsl:when test="contains($text,$replace)"> 
     <xsl:value-of select="substring-before($text,$replace)"/> 
     <xsl:value-of select="$with"/> 
     <xsl:call-template name="replace-string"> 
      <xsl:with-param name="text" select="substring-after($text,$replace)"/> 
      <xsl:with-param name="replace" select="$replace"/> 
      <xsl:with-param name="with" select="$with"/> 
     </xsl:call-template> 
     </xsl:when> 
     <xsl:otherwise> 
     <xsl:value-of select="$text"/> 
     </xsl:otherwise> 
    </xsl:choose> 
    </xsl:template> 

</xsl:stylesheet> 

的XSLT 1.0解決方案使得使用建議由Dimitre Novatchev here和馬德斯·漢森的回答​​給出。

XSLT 2.0解決方案更加優雅,使用character-map來控制輸出的序列化。請確保您也跳過了&字符(&amp;apos;而不是&apos;)。

樣式表(XSLT 2.0)

<?xml version="1.0" encoding="UTF-8"?> 

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 

    <xsl:output method="xml" indent="yes" use-character-maps="apo"/> 
    <xsl:strip-space elements="*"/> 

    <xsl:character-map name="apo"> 
     <xsl:output-character character="&apos;" string="&amp;apos;"/> 
    </xsl:character-map> 

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

    <xsl:template match="bar"> 
     <xsl:copy> 
      <xsl:text>this_</xsl:text> 
      <xsl:apply-templates/> 
     </xsl:copy> 
    </xsl:template> 

    <xsl:template match="foobar"/> 

</xsl:stylesheet> 

輸出(撒克遜9.5 2.0,的Xalan 2.7.1 1.0)

<?xml version="1.0" encoding="UTF-8"?> 
<input> 
    <foo>John&apos;s bar</foo> 
    <bar>this_test</bar> 
</input> 
+0

您在XSLT 1.0使用替換()。 –

+0

你說得對。我編輯了我的帖子。對不起,今天有點「困惑」。 –