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
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