如何在XSLT之后保留空XML标签 - 防止它们从<b> </b>折叠到<b> </b>

时间:2009-06-11 08:43:13

标签: java xml xslt

假设我有一个非常简单的XML,其空标记为“B”:

<Root>
  <A>foo</A>
  <B></B>
  <C>bar</C>
</Root>

我目前正在使用XSLT删除一些标签,例如“C”:

<?xml version="1.0" ?>

<xsl:stylesheet version="2.0" xmlns="http://www.w3.org/1999/XSL/Transform" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

<xsl:output method="xml" indent="no" encoding="utf-8" omit-xml-declaration="yes" />

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

<xsl:template match="C" />

</xsl:stylesheet>

到目前为止确定,但问题是我最终得到这样的输出:

<Root>
  <A>foo</A>
  <B/>
</Root>

当我真正想要的时候:

<Root>
  <A>foo</A>
  <B></B>
</Root>

有没有办法防止'B'崩溃?

感谢。

11 个答案:

答案 0 :(得分:9)

好的,所以这里对我有用:

<xsl:output method="html">

答案 1 :(得分:3)

试试这个:

<script type="..." src="...">&#160;</script>

您的HTML输出将是:

<script type="..." src="..."> </script>

&#160;可防止折叠,但会转换为空格。它过去对我有用。

答案 2 :(得分:2)

没有标准的方法,因为它们是等价的;您可能能够找到具有此行为选项的XSLT引擎,但我不知道。

如果您将此传递给使用此语法无法接受空标记的第三方,则您可能必须自己对输出进行后处理(或说服第三方修复其XML解析)

答案 3 :(得分:2)

决定如何呈现XML标记由XSLT引擎决定,因为解析器应该看到两个变体之间没有区别。但是,在输出HTML时,这是一个常见问题(例如,对于<textarea><script>标记。)最简单(但很难看)的解决方案是在标记内添加一个空格(这确实会改变含义)虽然标签略有。)

答案 4 :(得分:1)

这是一个很长时间的问题,我终于使用一个简单的解决方案。 添加&lt; xsl:text /&gt;如果你有空格字符。我在帮助器类中添加了一个空格。 &LT; XSL:选择&GT;  &lt; xsl:when test =“$ textAreaValue =''”&gt;    &LT; XSL:文本/&GT;  &LT; / XSL:当&GT;  &LT; XSL:否则&GT;    &lt; xsl:value-of select =“$ textAreaValue”/&gt;  &LT; / XSL:否则&GT; &LT; / XSL:选择&GT;

答案 5 :(得分:1)

它们并不总是等同的。许多浏览器无法处理&lt; script type =“...”src =“...”/&gt;并想要一个单独的结束标记。我在使用PHP的xml / xsl时遇到了这个问题。输出“html”不起作用,我仍在寻找解决方案。

答案 6 :(得分:1)

还应该有另一种方法(仅限XSLT2?):“xhtml”(see another thread)。 这可以防止您的代码崩溃,也不会从&lt; meta&gt;等

元素中删除结束标记

答案 7 :(得分:0)

没有。 2在语法上是相同的,所以你不必担心

答案 8 :(得分:0)

如果是或 ,那应该不是问题。但是,如果您使用的另一个工具只需要 方式的空XML标记,那么您就会遇到问题。一个不太优雅的方法是通过XSLT代码在凝视和结束'B'标签之间添加一个空格。

答案 9 :(得分:0)

<xsl:text disable-output-escaping="yes">
<![CDATA[<div></div>]]>
</xsl:text>

这适用于C#的XslCompiledTransform类与.Net 2.0,但几乎可能在其他任何地方失败。除非您自己以编程方式执行transofrm,否则请勿使用;它完全不便携。

答案 10 :(得分:0)

已经晚了7年,但对于未来的读者,我将在这里逆势而上,提出原始问题的实际解决方案。不使用空格或输出指令修改原始文件的解决方案。

这个想法是使用一个空变量来欺骗解析器。

如果您只想为一个标签B执行此操作,我首先想到的是使用类似的东西来附加虚拟变量。

<xsl:variable name="dummyempty" select="''"/>

<xsl:template match="B">    
  <xsl:copy>
    <xsl:apply-templates select="@*" />
    <xsl:value-of select="concat(., $dummyempty)"/>
  </xsl:copy>    
</xsl:template>

但我发现事实上,即使是虚拟变量也不是必需的。这保留了空标记,至少在linux中使用xsltproc进行测试时:

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

要获得处理所有空标记的更通用的解决方案,请尝试以下方法:

  <xsl:variable name="dummyempty" select="''"/>

  <xsl:template match="*[. = '']">
    <xsl:copy>
        <xsl:apply-templates select="node()|@*" />
        <xsl:value-of select="$dummyempty"/>
    </xsl:copy>
  </xsl:template>

同样,根据解析器的智能程度,您甚至可能不需要虚拟变量。