开发者

Why does <xsl:for-each select="text()"> ignore blank spaces?

Why does <xsl:for-each select="text()"> ignore blank spaces?

Example XML Source:

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

Example XSL:

<xsl:template match="body">
    <output>
        <xsl:for-each select="text()">
            <text>
                 <xsl:value-of select="."/>
            </text>
        </xsl:for-each>
    </output>
&开发者_开发知识库lt;/xsl:template>

I would expect this output:

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

But what I get is this:

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

Can someone give me some insight into how this works?

Thanks!


There are differents choices made from every XSLT processor (in fact from the XML tree provider) about white space only text nodes from input source.

Most of them (the most that count...) respect the xsl:preserve-space instruction.


It's not that <xsl:for-each> ignores blank text nodes, but rather, whitespace-only text nodes may get stripped upon parsing the input document, before your stylesheet templates ever see them.

According to the XSLT spec, XSLT by default strips whitespace-only text nodes from the stylesheet document except in <xsl:text> elements; but does not strip them from the source document unless you use <xsl:strip-space>.

The XSLT 1.0 spec describes it this way:

After the tree for a source document or stylesheet document has been constructed, but before it is otherwise processed by XSLT, some text nodes are stripped. A text node is never stripped unless it contains only whitespace characters. Stripping the text node removes the text node from the tree. The stripping process takes as input a set of element names for which whitespace must be preserved. The stripping process is applied to both stylesheets and source documents, but the set of whitespace-preserving element names is determined differently for stylesheets and for source documents.

A text node is preserved if any of the following apply:

  • The element name of the parent of the text node is in the set of whitespace-preserving element names.

  • The text node contains at least one non-whitespace character. As in XML, a whitespace character is #x20, #x9, #xD or #xA.

  • An ancestor element of the text node has an xml:space attribute with a value of preserve, and no closer ancestor element has xml:space with a value of default.

Otherwise, the text node is stripped.

The xml:space attributes are not stripped from the tree.

NOTE: This implies that if an xml:space attribute is specified on a literal result element, it will be included in the result.

For stylesheets, the set of whitespace-preserving element names consists of just xsl:text.

For source documents, the set of whitespace-preserving element names is specified by xsl:strip-space and xsl:preserve-space top-level elements. These elements each have an elements attribute whose value is a whitespace-separated list of NameTests. Initially, the set of whitespace-preserving element names contains all element names. [emphasis mine] If an element name matches a NameTest in an xsl:strip-space element, then it is removed from the set of whitespace-preserving element names. If an element name matches a NameTest in an xsl:preserve-space element, then it is added to the set of whitespace-preserving element names.

So in summary, the stripping should not be happening with your source document... unless you are using the <xsl:strip-space> top-level element in your stylesheet. If you are not using <xsl:strip-space>, please tell us more about your XSLT processor, and your top-level stylesheet elements.

According to this article, not every XSLT processor respects the default behavior described in the spec. You might try adding the following as a child of <xsl:stylesheet>, and see if it fixes the problem:

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

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜