XSLT将带空格的标记解释为空标记

时间:2012-03-12 22:45:08

标签: xml xslt whitespace

我有一个使用System.Xml.Xsl.XslCompiledTransform转换为XML的XSLT。问题是带空格的标签会转换为空标签。下面是重现问题的最小样本。

原始数据:

<data>
  <content>A</content>
  <content> </content>
  <content>B</content>
</data>

输出数据:

<?xml version="1.0" encoding="utf-8"?>
<data>
  <content>A</content>
  <content />
  <content>B</content>
</data>

第二个标签错了!这个空间不能那样吃。

XSLT

<?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"/>
<xsl:preserve-space elements="content"/>
<xsl:template match="//data">
  <xsl:copy-of select="." />
</xsl:template>
</xsl:stylesheet>

XSLT错了吗?或者我应该责怪.NET XSL转换器(我已尝试过3.5 SP1和4.0)?

请帮忙!

3 个答案:

答案 0 :(得分:2)

您需要包含(在顶级):

<xsl:preserve-space elements="content"/>

如果有多个节点类型必须保留空格,请将它们列在由空格分隔的elements属性中。这是documented here

答案 1 :(得分:2)

如果您使用的是msxml,则默认情况下会记录与xml规范不一致的内容并删除空白区域。您可以将xml:space="preserve"添加到元素中,以便正确处理该文件中的空格,或者通过API调用msxml(但如果在Internet Explorer中直接解析xml则不行)将其preserveWhitespace属性设置为true {{3 }}

与空格问题无关

<xsl:template match="//data/content">
  <xsl:element name="{title}">
    <xsl:apply-templates select="//data/content"/>
  </xsl:element>
</xsl:template>

永远不会被执行,因为匹配data的模板只是复制整个文档,而不是递归地应用模板。如果 被执行,它将无限循环,如上所述,对于每个内容元素,将模板应用于每个内容元素。

UPDATE 如果你不需要保留确切的空白区域,只需要放入一个空格使其非空,那么你可以通过在样式表中放回空格来纠正破解的解析,先修复一下,这样就可以递归地应用模板,然后为空内容元素添加一个额外的模板,通过添加空格使它们非空。

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

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

 <xsl:template match="content[not(node())]">
  <xsl:copy>
   <xsl:copy-of select="@*"/>
   <xsl:text> </xsl:text>
  </xsl:copy>
 </xsl:template>

</xsl:stylesheet>

答案 2 :(得分:2)

正如大卫指出的那样,问题是在进入XSLT之前空间被剥离了。使用.NET时的解决方案是使用XmlReader来读取输入XML - 这段代码可以解决问题:

  XslCompiledTransform transform = new XslCompiledTransform();
  transform.Load(@"c:\temp\space.xslt");
  using (XmlReader reader = XmlReader.Create(@"c:\temp\spaceSample.xml")) {
    using (XmlWriter writer = XmlWriter.Create(@"c:\temp\space.xml")) {
      transform.Transform(reader, writer);
    }
  }

输入文件中的spaceSample.xmlspace.xml是输出,space.xslt是转换。

(使用.NET 4.0测试)