为什么<xsl:for-each select =“text()”>忽略空格?</xsl:for-each>

时间:2010-11-18 19:54:29

标签: xslt

为什么<xsl:for-each select="text()">会忽略空格?

示例XML源:

<body>
Things<note>such as people</note> <note>or animals</note>act in crazy ways.
</body>

示例XSL:

<xsl:template match="body">
    <output>
        <xsl:for-each select="text()">
            <text>
                 <xsl:value-of select="."/>
            </text>
        </xsl:for-each>
    </output>
</xsl:template>

我希望这个输出:

<output>
    <text>Things</text><text> </text><text>act in crazy ways.</text>
</output>

但我得到的是:

<output>
    <text>Things</text><text>act in crazy ways.</text>
</output>

有人可以告诉我一些有用的方法吗?

谢谢!

2 个答案:

答案 0 :(得分:3)

每个XSLT处理器(实际上来自XML树提供程序)都有关于输入源中仅空白文本节点的不同选择。

大部分(最重要的......)都尊重xsl:preserve-space指令。

答案 1 :(得分:2)

并不是<xsl:for-each>忽略空白文本节点,而是在样式表模板看到它们之前,解析输入文档时可能会剥离仅空白文本节点。

根据XSLT规范,默认情况下,XSLT会从样式表文档中删除仅空白文本节点,但<xsl:text>元素除外;但除非您使用<xsl:strip-space>,否则不会将其从源文档中删除。

XSLT 1.0 spec以这种方式描述:

  

在源文档树之后   或样式表文件已经   建造,但在它之前   否则由XSLT处理,一些文本   节点被剥离。文本节点是   从不剥离,除非它只包含   空白字符。剥离   text节点从中删除文本节点   那个树。剥离过程需要   作为输入的一组元素名称   哪个空白必须保留。   剥离过程适用于   样式表和源文档,   但是保留了空白的一组   元素名称已确定   不同的样式表和   来源文件。

     

如果有任何文本节点,则会保留该文本节点   以下申请:

     
      
  • 文本节点的父节点的元素名称位于保留空白元素名称的集合中。

  •   
  • 文本节点至少包含一个非空白字符。与XML一样,空格字符为#x20,#x9,#xD或#xA。

  •   
  • 文本节点的祖先元素具有值为preserve的xml:space属性,并且没有更近的祖先元素具有值为default的xml:space。

  •   
     

否则,文本节点被剥离。

     

xml:space属性不是   从树上剥下来。

     

注意:这意味着如果在a上指定了xml:space属性   文字结果元素,它将是   包含在结果中。

     

对于样式表,一组   保留空格的元素名称   仅包含xsl:text。

     

  

     

  

     

对于源文档,请设置   保留空格的元素名称是   由xsl指定:strip-space和   xsl:preserve-space顶级元素。这些元素每个都有一个elements属性,其值是以空格分隔的NameTests列表。 最初,保留空白元素名称的集合包含所有元素名称。 [emphasis mine]如果元素名称与xsl:strip-space元素中的NameTest匹配,则将其从集合中删除保留空格的元素名称。如果元素名称与xsl:preserve-space元素中的NameTest匹配,则将其添加到保留空白元素名称的集合中。

总而言之,除非您在样式表中使用<xsl:strip-space>顶级元素,否则不应该使用源文档进行剥离。如果您没有使用<xsl:strip-space>,请告诉我们有关您的XSLT处理器和顶级样式表元素的更多信息。

根据this article,并非每个XSLT处理器都遵守规范中描述的默认行为。您可以尝试将以下内容添加为<xsl:stylesheet>的子项,并查看它是否解决了问题:

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