2016-06-12 43 views
1

我有一個需求,即需要在CDATA中替換特定標記。 例如,使用XSLT模板子如何在XSLT中替換CDATA中的標記

<MASTER_COMMENTS> 
<![CDATA[<pre> Nice Work done </pre>]]> 
</MASTER_COMMENTS> 

<MASTER_COMMENTS> 
<![CDATA[<span> Nice Work done </span>]]> 
</MASTER_COMMENTS> 

你能幫我寫一下嗎?

我嘗試以下,但它不工作

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
<xsl:output omit-xml-declaration="yes" indent="yes"/> 
<xsl:strip-space elements="*"/> 
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes" cdata-section-elements="//MASTER_COMMENTS"/> 

<xsl:template match="pre"> 
     <span><xsl:value-of select="."/></span> 
</xsl:template> 

+0

CDATA始終是文字,從未標籤。 –

+0

你不能。所有XML解析器(包括XSLT處理器中使用的XML解析器)都不應該解析CDATA(只作爲原始文本傳遞)。 – grochmal

回答

1
<xsl:template match="pre"> 

不會匹配您輸入任何東西,因爲CDATA節包含純文本數據,而不是XML標記。

如果可以,請執行兩遍轉換:首先,禁用輸出轉義MASTER_COMMENTS並將結果保存到文件;然後將結果文件處理爲「普通」XML。

或者,您可以使用字符串函數,例如嘗試和處理的內容:

<xsl:template match="MASTER_COMMENTS"> 
    <xsl:copy> 
     <xsl:value-of select="substring-before(., '&lt;pre&gt;')" /> 
     <xsl:text>&lt;span&gt;</xsl:text> 
     <xsl:value-of select="substring-before(substring-after(., '&lt;pre&gt;'),'&lt;/pre&gt;') " /> 
     <xsl:text>&lt;/span>&gt;</xsl:text> 
     <xsl:value-of select="substring-after(., '&lt;/pre&gt;') " /> 
    </xsl:copy> 
</xsl:template> 

注意,這個例子假定有恰恰是在處理文本一個pre「元素」。

0

嗯,你可以,但你必須做文本替換而不是模板匹配...請注意,這將是非常困難的情況下,當你可能沒有<pre>甚至不止一個這樣的標籤被替換。如果這是你的樣式表是什麼主要的,我會建議使用文本轉換

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

<xsl:output method="text" /> 

<xsl:template match="/"> 
    <xsl:text>&lt;TOP></xsl:text> 
     <xsl:apply-templates/> 
    <xsl:text>&lt;/TOP></xsl:text> 
</xsl:template> 

<xsl:template match="MASTER_COMMENTS"> 
    <xsl:text>&lt;MASTER_COMMENTS></xsl:text> 
     <xsl:value-of select="."/> 
    <xsl:text>&lt;/MASTER_COMMENTS></xsl:text> 
</xsl:template> 

</xsl:transform> 

使可作爲「文本」的內容,然後使用該文本作爲XML輸入你轉換,然後可在使用以前在CDATA部分內部的正常模板匹配。

對於文本的方法,請參閱michael.hor257k的答案。

0

如果包含XML標記的節點被錯誤地標記爲CDATA,則XML解析器將簡單地返回字符數據,並提取標記,您需要將該字符數據放入第二個解析階段。您可以通過調用parse-xml()函數在XSLT 3.0中完成此操作;在其他XSLT處理器中,您可以使用擴展功能做同樣的事情。

1

這裏是同時使用parse-xmlserialize實現這個需求的XSLT 3.0樣式表,它工作正常,我與撒克遜9.7 HE:

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

    <xsl:output cdata-section-elements="MASTER_COMMENTS"/> 

    <xsl:template match="MASTER_COMMENTS"> 
     <xsl:copy> 
      <xsl:variable name="content"> 
       <xsl:apply-templates select="parse-xml(.)"/> 
      </xsl:variable> 
      <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($content, $ser-params/*)"/> 
     </xsl:copy> 
    </xsl:template> 

    <xsl:template match="pre"> 
     <span> 
      <xsl:apply-templates/> 
     </span> 
    </xsl:template> 

</xsl:stylesheet> 

輸出是

<?xml version="1.0" encoding="UTF-8"?><MASTER_COMMENTS><![CDATA[<span> Nice Work done </span>]]></MASTER_COMMENTS>