Re: [xsl] extracting tree from flat xml data

Subject: Re: [xsl] extracting tree from flat xml data
From: Jeni Tennison <mail@xxxxxxxxxxxxxxxx>
Date: Wed, 14 Mar 2001 09:52:03 +0000
Hi Larry,

> The value for id is based on the relationship in the heirarchy. I
> have a JSP version of this working but need an XSLT solution also.
> It seems some processing of ancestors and their siblings is in order
> to build the value for id but the exact magic eludes me. The logic
> must initiated from within the 'node' template (no for-each
> processing by a "higher" template, ie data or person ). Any
> suggestions?

Hmm... I think that you can get the node that's higher in the
hierarchy by finding the nearest preceding sibling whose depth is one
less than the depth of the current node.  So have an id mode template
that looks like:

<xsl:template match="person" mode="id">
   <xsl:variable name="depth" select="node/@depth" />
   <xsl:variable name="parent"
      select="preceding-sibling::person[node/@depth = $depth - 1][1]"/>
   <xsl:apply-templates select="$parent" mode="id" />
   <xsl:text>_</xsl:text>
   ...
</xsl:template>

The ... is where you get the number for the ID. Getting the number
involves counting all the person elements that precede this one, whose
node/@depth is the same as this one, and who also have $parent as
their parent (you can just test that by making sure that $parent comes
before the node), plus one:

count(
  preceding-sibling::person
    [node/@depth = $depth and
     preceding-sibling::person[count(.|$parent) = 1]])
+ 1

So the full template is:

<xsl:template match="person" mode="id">
   <xsl:variable name="depth" select="node/@depth" />
   <xsl:variable name="parent"
      select="preceding-sibling::person[node/@depth = $depth - 1][1]"/>
   <xsl:apply-templates select="$parent" mode="id" />
   <xsl:text>_</xsl:text>
   <xsl:value-of select="count(preceding-sibling::person
                                 [node/@depth = $depth and
                                  preceding-sibling::person
                                     [count(.|$parent) = 1]]) + 1" />
</xsl:template>

And you call it with:

<xsl:template match="person">
   <node>
      <xsl:attribute name="id">
         <xsl:text>node</xsl:text>
         <xsl:apply-templates select="." mode="id" />
      </xsl:attribute>
      ...
   </node>
</xsl:template>

I hope that helps,

Jeni

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



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


Current Thread