Re: [xsl] Generically Finding Parent Elements

Subject: Re: [xsl] Generically Finding Parent Elements
From: Wendell Piez <wapiez@xxxxxxxxxxxxxxxx>
Date: Tue, 06 May 2008 16:52:10 -0400

This is a grouping problem, since removing duplicates from your list is tantamount to grouping them by name.

In XSLT 2.0, try this as the only template in a stylesheet:

<xsl:template match="*">
  <xsl:param name="this-ilk" select="."/>
  <xsl:for-each select="ancestor::*">
    <xsl:text>  </xsl:text>
  <xsl:value-of select="name()"/>
  <xsl:for-each-group select="$this-ilk/*" group-by="name()">
    <xsl:apply-templates select=".">
      <xsl:with-param name="this-ilk" select="current-group()"/>

This is pretty subtle stuff. In prose:

Match an element. Along with it, accept a parameter $this-ilk. If not given, $this-ilk will be the element matched.

Write out a line break, indent two spaces for every ancestor element, and write out the element's name.

Select the element children of $this-ilk in groups, grouping them by name. (Remember if $this-ilk was not given, the element's children will be selected, again grouped by name.)

Apply this same template to the first element in the group (referred to as "." when grouping), providing the entire group as $this-ilk, so when the template is matched to the element, all its siblings of the same name will come along with it.

This will descend the tree recursively. Note that given some "shaggy" document structures, like-named elements may appear twice, but never with exactly the same ancestry.

I hope this helps. This can also be done in XSLT 1.0, but much less conveniently.


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

Current Thread