XML: Collecting ancestors

Y

yurick

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
 
E

Ed Beroset

yurick said:
<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
 

Ask a Question

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

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,995
Messages
2,570,230
Members
46,819
Latest member
masterdaster

Latest Threads

Top