This is the mail archive of the xsl-list@mulberrytech.com mailing list .


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

Re: Numbering


Hi Kobily,

> Here is the real case:
>
> Part of the template match="root"
> <select size="6" name="available">
> <xsl:apply-templates select="*|@*|text()"/>
> </select>
>
> The template I´m calling:
> <xsl:template match="@*|text()">
> <xsl:if test="normalize-space(.)!=''">
> <option value="{position()}">
> <xsl:for-each select="ancestor::*">/<xsl:value-of 
> select="local-name(.)"/></xsl:for-each>
> </option>
> </xsl:variable>
> </xsl:if>
> </xsl:template>

I don't believe that is the template that you're applying, since it
has a end xsl:variable tag in it without a start xsl:variable tag, but
I get the idea. And from the result I guess you're doing this with an
input of:

<root>
  <url>foo</url>
  <tags>
    <a>foo</a>
    <b>foo</b>
    <c>foo</c>
    ...
  </tags>
</root>

It appears that what you want to do is to get all the
non-whitespace-only text nodes in the document and go through them one
by one, constructing the option values that you desire.

The position() function gives you the position of the context node
within the context node list. When you use it within a template, it
gives you the position of the node that you're processing (the text
node that's matched by the template) within the set of nodes that have
been selected to which to apply templates.

You're using the built-in templates to travel down the source node
tree. When you apply templates in the template matching the root node,
you tell the processor to apply templates to the child elements (url
and tags), attributes (none) and child text nodes (only whitespace) of
the root element. You haven't got a template for (for example) the url
element, so the processor uses the built-in template:

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

The processor applies templates to all the children of the url element
- there's only one of them, which is a text node. When the processor
applies the template that you've written, matching the text node, the
text node (child of the url element) is the only node in the context
node list, so it naturally has a position() of 1. The same goes for
the other text nodes.

To use position() to get your sequential numbering, you need to make
the context node list hold all the nodes you're interested in (all the
non-whitesapce-only text nodes). You can do this by applying templates
to them directly. You could get all the non-whitespace-only text nodes
in the document using:

  //text()[normalize-space()]

Or preferably you could remove all the whitespace-only text nodes from
the document using the top-level element:

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

and then the only text nodes that you'd get with //text() would be the
ones with some information in them.

So in your template matching the root element, you should then have:

  <select size="6" name="available">
    <xsl:apply-templates select="//text()"/>
  </select>

And you should have a template that matches the text nodes; you don't
have to worry about whether they have any text in them or not (because
you're not applying templates to ones that haven't), and you can use
position() to get an incremental counter for the options.

<xsl:template match="text()">
  <option value="{position()}">
    <xsl:for-each select="ancestor::*">
      <xsl:text />/<xsl:value-of select="local-name()" />
    </xsl:for-each>
  </option>
</xsl:template>

If you want to ignore some of the text nodes then you can use a
predicate so that you only select the nodes that you're interested in.

There are other methods to approach this, using xsl:number or using
recursive templates, but I think that this is the easiest and most
efficient method and is likely to be all that you need to do. If there
are added complications that you haven't yet divulged, then do let us
know.

I hope that helps,

Jeni

---
Jeni Tennison
http://www.jenitennison.com/


 XSL-List info and archive:  http://www.mulberrytech.com/xsl/xsl-list


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]