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: recursions?


Hi Dennis,

> Since the template doesn't know in which level of the hierarchy it
> is, it can't indent the output correctly.
>
> How would you do this? Is there a way to recursively traverse the
> nodes? So when I'm at a group node, it would call a template to
> check again for group and field and branch off from there
> recursively?

XSLT is designed to work in this kind of recursive way.  In your case,
as you describe, you would have two templates: one matching group
elements and one matching field elements, and the different templates
would do different things.

This is a very neat way of doing it if you're producing HTML and using
CSS to produce the indentation that you want.  You can use div
elements in HTML to add indentation at each level (or if you want a
quick-and-dirty way, use blockquote elements):

<xsl:template match="group">
   <div class="indent">
      GROUP-LEVEL
      <xsl:apply-templates />
   </div>
</xsl:template>

<xsl:template match="field">
   FIELD-LEVEL
</xsl:template>

If you're producing text, on the other hand, then the easiest way to
achieve the indentation is to pass down a 'indent' parameter from
template to template.  You can make a template accept a parameter with
a xsl:param element.  When you apply templates to the child elements
of the group element, you need to pass on the parameter with the
xsl:with-param element. At each group element, add some more to the
indent that you pass down by concatenating some more spaces to the
indent:

<xsl:template match="group">
   <xsl:param name="indent" />
   <xsl:value-of select="$indent" />
   <xsl:text>GROUP-LEVEL&#xA;<xsl:text>
   <xsl:apply-templates>
      <xsl:with-param name="indent" select="concat($indent, '   ')" />
   </xsl:apply-templates>
</xsl:template>

<xsl:template match="field">
   <xsl:param name="indent" />
   <xsl:value-of select="$indent" />
   <xsl:text>FIELD-LEVEL&#xA;</xsl:text>
</xsl:template>

If you don't like this approach, you could continue to apply templates
to all the descendants and then work out the depth of the element by
counting how many ancestors it has with:

  count(ancestor::*)

and use that as the basis for an indentation or whatever.  However,
this is a lot more fiddly and it's likely to be a lot more inefficient
than working going with the XSLT flow as described above.

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]