Altova Mailing List Archives


Re: Counting lines of output in a recursion

From: "Dimitre Novatchev" <dnovatchev@-----.--->
To: NULL
Date: 12/25/2003 10:59:00 PM
"Andy Bolsover" <andybolsover@y...> wrote in message
news:d41841d4.0312251256.41e595d7@p......
> For purposes of this question, I am a very old man. The names of my
> children and their children are contained in an XML file (see below).
> The XML contains details of the relationships (RELN) of parents (PRNT)
> and children (CHILD)
>
> The XML source is as follows :
>
> <?xml version='1.0'   encoding='UTF-8'    standalone='yes'?>
> <?xml-stylesheet type='text/xsl' href='Descendants.xsl'?>
> <GENI>
> <RELN>
> <PRNT>Me</PRNT>
> <CHLD>Alice</CHLD>
> </RELN>
> <RELN>
> <PRNT>Alice</PRNT>
> <CHLD>Bobby</CHLD>
> </RELN>
> <RELN>
> <PRNT>Alice</PRNT>
> <CHLD>Colin</CHLD>
> </RELN>
> <RELN>
> <PRNT>Bobby</PRNT>
> <CHLD>David</CHLD>
> </RELN>
> </GENI>
>
> I want to display the names of my descendants using XSL recursion.
> Each name is on a new line of output and I want to number the names in
> two different ways.
>
> First numbering system:
> The display should number each generation - I am generation 0 and my
> children are generation 1, grandchildren are generation 2 etc. I have
> written some XSL which successfully does this.
>
> Second numbering system:
> The display should also number each line of output, but I can not
> figure out how to do this. The numbering system is very simple; I want
> the first name displayed to be number 1, the second name displayed
> should be number 2 etc.
>

[snip]

>
> Has anyone got any suggestions on how I can number each line of
> output?

Yes, it is pretty straightforward. The only thing is that the hierarchy has
to be traversed in a particular way -- all persons at a given level before
all at the next level. Here's one possible solution.

This transformation:

<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

  <xsl:key name="kChildren" match="CHLD"
   use="preceding-sibling::PRNT[1]"/>

  <xsl:template match="/">
    <html>
      <head>
        <TITLE>Family Tree</TITLE>
      </head>
      <body >
        <xsl:call-template name="printChildren">
          <xsl:with-param name="pChildren" select="key('kChildren', 'Me')"/>
          <xsl:with-param name="pGen" select="1" />
          <xsl:with-param name="pRowNum" select="1" />
        </xsl:call-template>
      </body >
    </html>
  </xsl:template>

  <xsl:template name="printChildren">
    <xsl:param name="pGen" select="1" />
    <xsl:param name="pRowNum" select="1"/>
    <xsl:param name="pChildren" select="/.."/>

    <xsl:if test="$pChildren">
      <xsl:for-each select="$pChildren">
        <xsl:value-of select="concat($pGen, ': ',
                                     $pRowNum + position() - 1,
                                      ': ',.)" />
        <br/>
      </xsl:for-each>

      <xsl:call-template name="printChildren">
        <xsl:with-param name="pGen" select="$pGen + 1" />
        <xsl:with-param name="pChildren"
         select="key('kChildren', $pChildren)"/>
        <xsl:with-param name="pRowNum" select="$pRowNum +
count($pChildren)"/>
      </xsl:call-template>
    </xsl:if>
  </xsl:template>
</xsl:stylesheet>

when applied on your source.xml:

<GENI>
  <RELN>
    <PRNT>Me</PRNT>
    <CHLD>Alice</CHLD>
  </RELN>
  <RELN>
    <PRNT>Alice</PRNT>
    <CHLD>Bobby</CHLD>
  </RELN>
  <RELN>
    <PRNT>Alice</PRNT>
    <CHLD>Colin</CHLD>
  </RELN>
  <RELN>
    <PRNT>Bobby</PRNT>
    <CHLD>David</CHLD>
  </RELN>
</GENI>


produces the desired result (displayed by a browser as):

1: 1: Alice
2: 2: Bobby
2: 3: Colin
3: 4: David







Hope this helped.







Dimitre Novatchev.
FXSL developer, XML Insider,

http://fxsl.sourceforge.net/ -- the home of FXSL
Resume: http://fxsl.sf.net/DNovatchev/Resume/Res.html


Disclaimer

These Archives are provided for informational purposes only and have been generated directly from the Altova mailing list archive system and are comprised of the lists set forth on www.altova.com/list/index.html. Therefore, Altova does not warrant or guarantee the accuracy, reliability, completeness, usefulness, non-infringement of intellectual property rights, or quality of any content on the Altova Mailing List Archive(s), regardless of who originates that content. You expressly understand and agree that you bear all risks associated with using or relying on that content. Altova will not be liable or responsible in any way for any content posted including, but not limited to, any errors or omissions in content, or for any losses or damage of any kind incurred as a result of the use of or reliance on any content. This disclaimer and limitation on liability is in addition to the disclaimers and limitations contained in the Website Terms of Use and elsewhere on the site.