Subject: Re: Create xml file with recursive childnodes
From: "Mukul Gandhi" <gandhi.mukul@xxxxxxxxx>
Date: Sat, 9 Aug 2008 10:44:50 +0530
|
Hi Mike,
I tried your solution, and it was producing something different than
with the OP wanted.
The following stylesheet works ...
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="2.0">
<xsl:output method="xml" indent="yes" />
<xsl:template match="Objs">
<xsl:variable name="temp">
<xsl:apply-templates select="obj[not(@name = ../obj/@child)]" />
</xsl:variable>
<xsl:call-template name="processTemp">
<xsl:with-param name="temp" select="$temp/*" />
</xsl:call-template>
</xsl:template>
<xsl:template match="obj">
<xsl:variable name="child" select="@child" />
<Obj name="{@name}">
<xsl:choose>
<xsl:when test="../obj[@name = $child]">
<xsl:apply-templates select="../obj[@name = $child]" />
</xsl:when>
<xsl:otherwise>
<Obj name="{$child}" />
</xsl:otherwise>
</xsl:choose>
</Obj>
</xsl:template>
<xsl:template name="processTemp">
<xsl:param name="temp" />
<xsl:for-each-group select="$temp" group-by="@name">
<Obj name="{@name}">
<xsl:call-template name="processTemp">
<xsl:with-param name="temp" select="current-group()/*" />
</xsl:call-template>
</Obj>
</xsl:for-each-group>
</xsl:template>
</xsl:stylesheet>
On Fri, Aug 8, 2008 at 1:46 PM, Michael Kay <mike@xxxxxxxxxxxx> wrote:
>
> Do this as a standard recursive descent of the input tree using
> xsl:apply-templates, but with one exception: instead of processing the
> physical XML children, you process the logical children selected using the
> foreign key relationship.
>
> Usually in this problem elements have a pointer to their parent node, in
> your case you have a pointer to each of the children, which makes it a
> little more difficult, but not much.
>
> <xsl:key name="nameKey" match="obj" use="@name"/>
>
> <xsl:template match="obj">
> <Obj name="@name">
> <xsl:for-each select="key('nameKey', @name)">
> <xsl:apply-templates select="key('nameKey', @child)"/>
> </xsl:for-each>
> </Obj>
> </xsl:template>
>
> Or you could condense it:
>
> <xsl:template match="obj">
> <Obj name="@name">
> <xsl:apply-templates select="key('nameKey', @name)/key('nameKey',
> @child)"/>
> </Obj>
> </xsl:template>
>
> but I thought that might be a bit confusing!
>
> Of course, you have to start by calling apply-templates on the "logical
> root" of the tree.
>
> Michael Kay
> http://www.saxonica.com/
--
Regards,
Mukul Gandhi
|