XML: Collecting ancestors

Discussion in 'XML' started by yurick, Jan 14, 2004.

  1. yurick

    yurick Guest

    Hello everybody,

    I'm quit newbie to XML/XSLT, would appreciate any help.

    There is XML like this:

    <person name="adam"/>
    <person name="eve"/>
    <person name="cain">
    <parent name="adam"/>
    <parent name="eve"/>
    </person>
    <person name="henoch">
    <parent name="cain"/>
    </person>

    I need to get output from transformation:

    adam(0)
    eve(0)
    cain(2): adam, eve
    henoch(3): cain, adam, eve

    i.e. name of the person, total number and list of all parents, grandparents,
    grand-grandparents, grand-grand-grandparents, etc.

    Is it possible to express this in XSLT with recursive of any deepness?
    Or maybe other technique is applicable here?

    -- Regards, Yurii
    yurick, Jan 14, 2004
    #1
    1. Advertising

  2. yurick

    Ed Beroset Guest

    yurick wrote:

    > <person name="henoch">
    > <parent name="cain"/>
    > </person>
    >
    > I need to get output from transformation:
    >
    > adam(0)
    > eve(0)
    > cain(2): adam, eve
    > henoch(3): cain, adam, eve


    First, since XML requires a single root tag, I added <people> around
    your collection of names. Second, I didn't add commas in the output
    stream, but that's just because I'm lazy. It's certainly possible to do.

    > Is it possible to express this in XSLT with recursive of any deepness?
    > Or maybe other technique is applicable here?


    Here's the modified input file:

    <?xml version="1.0" encoding="iso-8859-1"?>
    <people>
    <person name="adam"/>
    <person name="eve"/>
    <person name="cain">
    <parent name="adam"/>
    <parent name="eve"/>
    </person>
    <person name="henoch">
    <parent name="cain"/>
    </person>
    <person name="gladys"/>
    <person name="frank">
    <parent name="henoch"/>
    </person>
    <person name="jose">
    <parent name="gladys"/>
    <parent name="frank"/>
    </person>
    </people>

    And this is the XSLT I wrote:

    <?xml version="1.0" encoding="iso-8859-1"?>
    <xsl:stylesheet version="1.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xsd="http://www.w3.org/2001/XMLSchema"
    >

    <xsl:eek:utput method="text"/>

    <xsl:template match="/people">
    <xsl:apply-templates select="person"/>
    </xsl:template>

    <!-- for each person, print the name and ancestor count -->
    <xsl:template match="person">
    <xsl:value-of select="@name"/>
    <xsl:text>(</xsl:text>
    <xsl:apply-templates select="." mode="count-kin"/>
    <xsl:text>): </xsl:text>
    <!-- now name all of the ancestors -->
    <xsl:apply-templates select="." mode="name-kin"/>
    <xsl:text>
    </xsl:text>
    </xsl:template>

    <!-- recursively name the ancestors -->
    <xsl:template match="parent" mode="name-kin">
    <xsl:value-of select="concat(@name,' ')"/>
    <xsl:variable name="myname" select="@name"/>
    <xsl:apply-templates select="/people/person[@name=$myname]"
    mode="name-kin"/>
    </xsl:template>

    <!-- recursively name the ancestors -->
    <xsl:template match="person" mode="name-kin">
    <xsl:apply-templates select="parent" mode="name-kin"/>
    </xsl:template>


    <!-- recursively count the number of ancestors -->
    <xsl:template match="parent" mode="count-kin">
    <xsl:variable name="myname" select="@name"/>
    <xsl:variable name="ancestor-count">
    <xsl:apply-templates select="/people/person[@name=$myname]"
    mode="count-kin"/>
    </xsl:variable>
    <xsl:value-of select="$ancestor-count"/>
    </xsl:template>

    <!-- recursively count the number of ancestors -->
    <xsl:template match="person" mode="count-kin">
    <xsl:choose>
    <!-- only count ancestors if there are any -->
    <xsl:when test="count(parent)">
    <xsl:variable name="ancestor-count">
    <xsl:apply-templates select="parent" mode="count-kin"/>
    </xsl:variable>
    <xsl:value-of select="number($ancestor-count)+count(parent)"/>
    </xsl:when>
    <!-- no parents -->
    <xsl:eek:therwise>
    <xsl:value-of select="0"/>
    </xsl:eek:therwise>
    </xsl:choose>
    </xsl:template>

    </xsl:stylesheet>

    The results look like this:

    adam(0):
    eve(0):
    cain(2): adam eve
    henoch(3): cain adam eve
    gladys(0):
    frank(4): henoch cain adam eve
    jose(6): gladys frank henoch cain adam eve

    That should give you some ideas.

    Ed
    Ed Beroset, Jan 15, 2004
    #2
    1. Advertising

  3. yurick

    yurick Guest

    Ed Beroset <> wrote in message news:<fjlNb.8488$>...
    > That should give you some ideas.
    >
    > Ed


    Thank You!!!!!
    yurick, Jan 15, 2004
    #3
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Martin Pettersson

    Multiply ancestors in xsl

    Martin Pettersson, Oct 5, 2004, in forum: XML
    Replies:
    2
    Views:
    2,105
    Martin Pettersson
    Oct 18, 2004
  2. Replies:
    6
    Views:
    525
  3. andrew cooke
    Replies:
    2
    Views:
    277
    Vinay Sajip
    Apr 26, 2008
  4. Paolo Nusco Perrotta

    Trickery in the ancestors chain

    Paolo Nusco Perrotta, Jan 24, 2007, in forum: Ruby
    Replies:
    9
    Views:
    141
  5. Replies:
    3
    Views:
    176
Loading...

Share This Page