修复 CDATA 部分的缩进

发布于 2024-10-22 02:19:47 字数 2310 浏览 2 评论 0原文

我对 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>

Im completely new to XML/XSL/XSLT, and while i have been digging msdn, 3schools.com and google for the past hour i cant figure this one out. I think is because CDATA isnt parsed by xml, but I thought that as my edit did work on the node i should be able to fix this...

Note that this is not a very important issue, I just want to learn a little bit more of XSL and what better way than fixing stuff that doesnt seem to work as i want it to.

So... my script saves options on an XML file in which i will also save some code snippets which might contain characters that need to be escaped. A small example would be:

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

With the following xsl i get a fairly good indentation:

<!-- 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 -->

Well, basically it doesnt match CDATA sections, so googling around I found that i could do the following which helps a little but produces this output:

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

So the question is:

how do i tell xsl to indent the CDATA section as it does with everything else:

    <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>

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

夜还是长夜 2024-10-29 02:19:47

此转换

<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>
</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,'
'))">
     <xsl:value-of select="$pText"/>
    </xsl:when>

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

     <xsl:call-template name="replace">
      <xsl:with-param name="pText"
       select="substring-after($pText, '
')"/>
     </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" 属性指示 XSLT 处理器序列化任何 Snippet 的任何文本节点 元素作为 CDATA 节。

  3. 有一个模板可以覆盖身份模板 - 当匹配作为 Snippet 元素子级的文本节点时。

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

This transformation:

<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>
</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,'
'))">
     <xsl:value-of select="$pText"/>
    </xsl:when>

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

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

when applied on the provided XML document:

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

produces the wanted, correct result:

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

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

]]></Snippet>

Explanation:

  1. The identity rule copies every node "as-is".

  2. The cdata-section-elements="Snippet" attribute of <xsl:output> instructs the XSLT processor to serialize any text node of any Snippet element as a CDATA section.

  3. There is a single template that overrides the identity template -- when matching a text node that is a child of a Snippet element.

  4. The processing of any such text-node is done by calling the replace template, which replaces any NL character with NL followed by two tab characters. When these replacements are done, one last NL character is output, so that the end tag </Snippet> will be on a new line.

天涯离梦残月幽梦 2024-10-29 02:19:47

这有点笨拙,但它应该可以工作并且速度超级快。只需使用

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

This is kludgy but it should work and is super quick. Simply use <xsl:text>:

<xsl:copy />
<xsl:text>
</xsl:text>
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文