修复CDATA部分的缩进

时间:2011-03-14 21:25:59

标签: xml xslt

我是XML / XSL / XSLT的新手,虽然我过去一小时一直在挖掘msdn,3schools.com和google,但我无法想象这一点。我认为是因为CDATA没有被xml解析,但我认为当我的编辑在节点上工作时我应该能够解决这个问题......

请注意,这不是一个非常重要的问题,我只想学习更多的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部分,所以谷歌搜索我发现我可以做以下有助于一点但产生这个输出:

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>

2 个答案:

答案 0 :(得分: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. cdata-section-elements="Snippet"的{​​{1}}属性指示XSLT处理器将任何<xsl:output>元素的任何文本节点序列化为CDATA部分。

  3. 当匹配作为Snippet元素的子节点的文本节点时,有一个模板会覆盖标识模板。

  4. 任何此类文本节点的处理都是通过调用Snippet模板完成的,该模板用NL替换任何NL字符,后跟两个制表符。完成这些替换后,将输出最后一个NL字符,以便结束标记replace将在新行上。

答案 1 :(得分:0)

这是kludgy但它应该工作,并且超级快。只需使用<xsl:text>

<xsl:copy />
<xsl:text>
</xsl:text>