2009-09-01 101 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部分对链中的下一个工具很重要,因此我手动输出它们。