Re: [xsl] traversing up nodes until a certain attribute, then back to current node

Subject: Re: [xsl] traversing up nodes until a certain attribute, then back to current node
From: "G. Ken Holman" <gkholman@xxxxxxxxxxxxxxxxxxxx>
Date: Tue, 27 Mar 2007 22:19:41 +0100
At 2007-03-27 08:14 -0700, xslt user wrote:
Here is sample XML
...
which I want to transform into this:
...
just giving the element name if no ancestor has the
attribute "id" and giving the closest ancestor "id" as
the starting point and all element names back to the
current node if it does have an ancestor with
attribute "id".

Here is what I have so far, but it's not enough.

I think you only need something such as what I have below.


...
but I need to process back until the current node (not
beyond it...) giving all element names along the way,
starting after the closest ancestor node with an
attribute "id".

I've done some searching and I might need to do some
XSLT grouping, but I'm not sure yet.  Can anyone help?

Because the elements are nested and not siblings, I believe you don't need grouping at all but can do it entirely with axes.


I hope this helps ... it does give you precisely the output that you quoted.

. . . . . . . . . . . . . . . Ken

t:\ftemp>type xsltacct.xml
<root>
  <zero>
        <one id="a">
          <two>
                <three id="c">
                  <four id="d">
                        <five>
                          <six>
                                <seven/>
                          </six>
                        </five>
                  </four>
                </three>
          </two>
        </one>
  </zero>
</root>
t:\ftemp>type xsltacct.xsl
<?xml version="1.0" encoding="US-ASCII"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform";
                version="1.0">

<xsl:output method="text"/>

<xsl:template match="*">
  <xsl:choose>
    <xsl:when test="not(ancestor-or-self::*[@id])">
      <xsl:value-of select="name(.)"/>
    </xsl:when>
    <xsl:otherwise>
      <xsl:value-of select="ancestor-or-self::*[@id][1]/@id"/>
      <xsl:if test="not(@id)">
        <xsl:for-each
           select="ancestor-or-self::*[count(ancestor::*[@id])=
                                       count(current()/ancestor::*[@id])]">
          <xsl:text> </xsl:text>
          <xsl:value-of select="name(.)"/>
        </xsl:for-each>
      </xsl:if>
    </xsl:otherwise>
  </xsl:choose>
  <xsl:text>
</xsl:text>
  <xsl:apply-templates select="*"/>
</xsl:template>

</xsl:stylesheet>
t:\ftemp>xslt xsltacct.xml xsltacct.xsl con
root
zero
a
a two
c
d
d five
d five six
d five six seven

t:\ftemp>

--
World-wide corporate, govt. & user group XML, XSL and UBL training
RSS feeds:     publicly-available developer resources and training
G. Ken Holman                 mailto:gkholman@xxxxxxxxxxxxxxxxxxxx
Crane Softwrights Ltd.          http://www.CraneSoftwrights.com/s/
Box 266, Kars, Ontario CANADA K0A-2E0    +1(613)489-0999 (F:-0995)
Male Cancer Awareness Aug'05  http://www.CraneSoftwrights.com/s/bc
Legal business disclaimers:  http://www.CraneSoftwrights.com/legal

Current Thread