2011-03-14 34 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