RE: [xsl] position()

Subject: RE: [xsl] position()
From: Wendell Piez <wapiez@xxxxxxxxxxxxxxxx>
Date: Mon, 02 Apr 2001 12:39:53 +0100
Hi Richard,

At 03:54 PM 4/2/01, you wrote [quoting David]:

> If you don't want that, then use select="*" just to select elements.

Or of course select="*|text()" for elements that contain text nodes.

> Or use xsl:number rather than position()
> David
Well yes, but I would have thought that xsl like

<xsl:template match="object">
        <xsl:value-of select="concat(position(),' ',@name)"/>

on input of

        <!-- hello -->
        <object name="first"/>
        <object name="second"/>
        <!-- hello -->
        <object name="third"/>
        <object name="fourth"/>

Would produce

1 first
2 second
3 third
4 fourth

and not

2 first
3 second
5 third
6 fourth

which seems to be the case.

Your expectation makes sense, but on balance it's best that the spec simply count comments rather than provide some complex logic -- even harder to understand -- to avoid them. XSLT could have left comments out of the source tree altogether. But they decided to let you work with the comments if you wanted: probably to support identity transforms and their variants, when necessary. As long as they're in the tree, it's better to expect you to reckon with them than have some fancy logic to see them sometimes but not others, which we'd all have to learn and complain about. This would make XPath much nastier than it is.

Whitespace-only text nodes make it bad enough already! :-) Note that even the result

2 first
3 second
5 third
6 fourth

is incorrect for the input you gave. Where'd the whitespace nodes go? This is an MS bug, I believe (can someone confirm?). The correct sequence should be 4, 6, 10, 12.

In any case, as David said a template

<xsl:template match="objects">
  <xsl:apply-templates select="*"/>

or even

<xsl:template match="*[not(text())]" priority="-1">
  <xsl:apply-templates select="*"/>

would solve this problem and get you 1, 2, 3, 4 as you expect.

Maybe some future version of XSLT could include an <xsl:strip-comments> (and <xsl:strip-processing-instructions>) analogue to <xsl:strip-space> to help deal with this situation. But there's no substitute for knowing what the source tree looks like and how XPath sees it.

Also on a related point how can I output the preceding node if and
only if it is a comment.

Try <xsl:copy-of select="preceding-sibling::node()[1][self::comment()]"/> (or xsl:value-of or whatever).

Good luck,

Wendell Piez                            mailto:wapiez@xxxxxxxxxxxxxxxx
Mulberry Technologies, Inc.      
17 West Jefferson Street                    Direct Phone: 301/315-9635
Suite 207                                          Phone: 301/315-9631
Rockville, MD  20850                                 Fax: 301/315-8285
  Mulberry Technologies: A Consultancy Specializing in SGML and XML

XSL-List info and archive:

Current Thread