2011-03-14 67 views
1

我完全不熟悉XML/XSL/XSLT,雖然我一直在挖掘msdn,3schools.com和谷歌過去一小時,我不能弄清楚這一點。我認爲是因爲CDATA未通過xml解析,但我認爲,因爲我的編輯確實在節點上工作,所以我應該可以修復此問題...修復CDATA節的縮進

請注意,這不是一個非常重要的問題,我只是想多學習一點XSL,還有比修復看起來不像我想要的東西更好的方法。

因此...我的腳本將選項保存在XML文件中,我將在其中保存一些可能包含需要轉義的字符的代碼片段。一個小例子是:

<Snippet title="Version Test"> 
<![CDATA[ 
version := "AHK Version: " a_ahkversion 
unicode := "& Supports Unicode: " (a_isunicode ? "Yes" : "No") 
Msgbox % version "`n" unicode 
]]> 
</Snippet> 

用下面的XSL,我收到了相當不錯的壓痕:

<!-- Extracted from: http://www.dpawson.co.uk/xsl/sect2/pretty.html (v2) --> 
<!-- Cdata info: http://www.altova.com/forum/default.aspx?g=posts&t=1000002342 --> 
<!-- Modified By RaptorX --> 
<xsl:stylesheet version="1.0" 
       xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 

<xsl:output method="xml" 
      indent="yes" 
      encoding="UTF-8" 
      cdata-section-elements="Snippet"/> 

<xsl:template match="*"> 
    <xsl:copy> 
     <xsl:copy-of select="@*" /> 
     <xsl:apply-templates /> 
    </xsl:copy> 
</xsl:template> 

<xsl:template match="comment()|processing-instruction()"> 
    <xsl:copy /> 
</xsl:template> 
</xsl:stylesheet> 
<!-- I have to keep the indentation here in this file as 
i want it to be on the XML file --> 

嗯,基本上它不匹配CDATA部分,所以周圍的Googling我發現我可以做下面這有助於一點點,但產生這樣的輸出:

xsl:copy-of select="@*|node()" /> << -- by adding that i match cdata nodes too 

Output: 
<Snippet title="Version Test"> 
    <![CDATA[ 
version := "AHK Version: " a_ahkversion 
unicode := "Supports Unicode: " (a_isunicode ? "Yes" : "No") 
Msgbox % version "`n" unicode 
    ]]></Snippet> <<-- here is the problem I cant seem to put a newline there lol 

所以,問題是:

我如何告訴XSL縮進CDATA部分,因爲它與一切做:

<root> 
     <child/> 
    </root> 

    <Snippet title="Version Test"> 
    <![CDATA[ 
    version := "AHK Version: " a_ahkversion 
    unicode := "Supports Unicode: " (a_isunicode ? "Yes" : "No") 
    Msgbox % version "`n" unicode 
    ]]> << --- this is what im looking for 
    </Snippet> 
+1

爲什麼重要的是文本要縮進?您要求序列化程序更改文檔的語義......或者說輸出序列化程序無法知道,在此特殊實例中,將空白插入到文本節點的中間不會更改語義。假設CDATA部分包含一些Python代碼......在每行的開頭插入額外的空格幾乎肯定會改變語義。 – 2011-03-14 21:33:28

+0

好問題,+1。查看我的答案,獲取完整且經過測試的解決方案,可真正縮進原始CDATA部分中的文本行。還提供了廣泛的解釋。 – 2011-03-15 03:01:03

回答

2

這種轉變

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

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

<xsl:template match="Snippet/text()"> 
    <xsl:call-template name="replace"/> 
    <xsl:text>&#xA;</xsl:text> 
</xsl:template> 

<xsl:template name="replace"> 
    <xsl:param name="pText" select="."/> 

    <xsl:if test="string-length($pText) >0"> 
    <xsl:choose> 
    <xsl:when test="not(contains($pText,'&#xA;'))"> 
    <xsl:value-of select="$pText"/> 
    </xsl:when> 

    <xsl:otherwise> 
    <xsl:value-of select= 
     "substring-before($pText, '&#xA;')"/> 
    <xsl:text>&#xA;&#9;&#9;</xsl:text> 

    <xsl:call-template name="replace"> 
     <xsl:with-param name="pText" 
     select="substring-after($pText, '&#xA;')"/> 
    </xsl:call-template> 
    </xsl:otherwise> 
    </xsl:choose> 
    </xsl:if> 
</xsl:template> 
</xsl:stylesheet> 

時所提供的XML文檔應用:

<Snippet title="Version Test"> 
<![CDATA[ 
version := "AHK Version: " a_ahkversion 
unicode := "& Supports Unicode: " (a_isunicode ? "Yes" : "No") 
Msgbox % version "`n" unicode]]> 
</Snippet> 

產生想要的正確結果

<Snippet title="Version Test"><![CDATA[ 

     version := "AHK Version: " a_ahkversion 
     unicode := "& Supports Unicode: " (a_isunicode ? "Yes" : "No") 
     Msgbox % version "`n" unicode 

]]></Snippet> 

說明

  1. 身份規則副本的每個節點 「原樣」。

  2. <xsl:output>cdata-section-elements="Snippet"屬性指示XSLT處理器來序列任何Snippet元件作爲CDATA部分的任何文本節點。

  3. 有一個覆蓋身份模板的單個模板 - 匹配Snippet元素的子節點的文本節點時。

  4. 通過調用replace模板來完成對任何此類文本節點的處理,該模板使用NL替換NL後跟兩個製表符。當這些替換完成後,會輸出最後一個NL字符,以便結束標記</Snippet>將在新行中。

+0

+1也用於顯示'cdata-section-elements'。 – Flack 2011-03-15 06:21:00

+0

+1是的。這似乎更合適的答案。雖然標識應該考慮到祖先,但至少對於大多數XSLT處理器(而不是MSXSL)來說。 – 2011-03-15 13:43:07

+0

@Alejandro:請稍等評論後停止刪除答案:(......或者我會害怕指出你答案中的任何問題 - 你可以糾正你的答案。至於縮進......好吧,我們必須有一個Javascript解析器才能正確執行Javascript程序的縮進 – 2011-03-15 14:27:45

0

這是kludgy,但它應該工作,超級快。簡單地使用<xsl:text>

<xsl:copy /> 
<xsl:text> 
</xsl:text> 
+0

我認爲輸出一些字符(NL,'#xA')而不能讀取是不明智的 – 2011-03-15 12:57:14

+0

@Alejandro:就像我說的,它是缺憾。 – 2011-03-15 13:25:51