2009-09-01 50 views
2

在將它交給另一個工具(InstallAnywhere本身)以更新某些值之前,我正在處理一個XML文檔(一個InstallAnywhere .iap_xml安裝程序)。但是,看起來我正在使用的XSLT轉換是從文檔剝離CDATA節(對於InstallAnywhere來說顯得非常重要)。XSLT處理器可以保留空的CDATA部分嗎?

我使用Ant 1.7.0,JDK 1.6.0_16和樣式表基礎上的身份:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> 
    <xsl:output method="xml" encoding="UTF-8" cdata-section-elements="string" /> 
    <xsl:template match="@*|node()"> 
    <xsl:copy> 
     <xsl:apply-templates select="@*|node()"/> 
    </xsl:copy> 
    </xsl:template> 
</xsl:stylesheet> 

基本上, 「串」 的節點,看起來像:

<string><![CDATA[]]></string> 

正在處理成:

<string/> 

從閱讀XSLT常見問題,我可以看到,發生的事情是合法的,就XSLT規範而言被關注到。有什麼辦法可以防止這種情況發生,並說服XSLT處理器發出CDATA段?

+0

有沒有你想要的理由? – skaffman 2009-09-01 21:31:38

+1

是的,當它看到表單時,InstallAnywhere(此樣式表之後的鏈中的下一個工具)會引發可怕的警告。 (我認爲它期望在DOM中存在一個子文本節點,或者,IA已經構建了一個不太完整的XML-XML解析器。) – 2009-09-01 21:51:01

+0

生成CDATA節的另一個原因:保留JavaScript代碼內聯腳本是XHTML文檔的一部分。 (截至今天)編碼的'<', '>'和'&'在JavaScript引擎/瀏覽器中沒有正確解釋。 – 2011-01-04 13:25:48

回答

0

爲此,您需要爲空string元素添加特殊情況並使用disable-output-escaping。我沒有螞蟻的副本進行測試,但下面的模板工作對我來說與libxmlxsltproc,表現出你所描述的相同的行爲:

<?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" omit-xml-declaration="yes" cdata-section-elements="string"/> 

    <xsl:template match="string"> 
     <xsl:choose> 
      <xsl:when test=". = ''"> 
       <string> 
        <xsl:text disable-output-escaping="yes"><![CDATA[]]></xsl:text> 
       </string> 
      </xsl:when> 

      <xsl:otherwise> 
       <xsl:copy-of select="."/> 
      </xsl:otherwise> 
     </xsl:choose> 
    </xsl:template> 

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

輸入:

<input> 
    <string><![CDATA[foo]]></string> 
    <string><![CDATA[]]></string> 
</input> 

輸出:

<input> 
    <string><![CDATA[foo]]></string> 
    <string><![CDATA[]]></string> 
</input> 
+0

在XSLT中,CDATA聲明本身的字符'<' and '>'必須被轉義,否則,CDATA應用於XSLT轉換的源XML。轉義標記爲: <![CDATA []] >如Brian Bassett的答案所示。 – 2011-01-04 13:26:54

+0

我原本以爲是這樣,但我在這裏展示的樣式表確實在'xsltproc'中有效。或者至少在去年我回答這個問題的時候就這麼做了! ;-) – 2011-01-06 19:39:30

0

一旦XML解析器完成XML,<![CDATA[abc]]>abc之間絕對沒有區別。對於一個空字符串也是如此 - <![CDATA[]]>根本沒有任何結果,並且被默默地忽略。它在XML模型中沒有表示。實際上,沒有辦法從CDATA和常規字符串中區分出來,並且在XML模型中也沒有任何表示。

對不起。

現在,你爲什麼要這個?也許有另一種解決方案可以幫助你?

+0

Installshield具有損壞的XML解析器;這個破解是必要的。 – Knyphe 2010-11-30 01:20:19

+0

(嘆...)從技術上講,如果它不完全符合,它就不能稱自己爲'XML解析器'。但現在我明白了。 – lavinio 2010-12-04 01:26:20

1

實測值的溶液:

<xsl:template match="string"> 
    <xsl:element name="string"> 
     <xsl:text disable-output-escaping="yes">&lt;![CDATA[</xsl:text><xsl:value-of select="text()" disable-output-escaping="yes" /><xsl:text disable-output-escaping="yes">]]&gt;</xsl:text> 
    </xsl:element> 
</xsl:template> 

我還從< xsl:output>元素中刪除了cdata-section-elements屬性。

基本上,由於CDATA部分對鏈中的下一個工具很重要,因此我手動輸出它們。