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

sl="http://www.w3.org/1999/XSL/Transform"
xmlns

sd="http://www.w3.org/2001/XMLSchema"
>
<xsl

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

therwise>
<xsl:value-of select="0"/>
</xsl

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