xsl-list
[Top] [All Lists]

Re: [xsl] Create xml file with recursive childnodes

2008-08-08 22:15:23
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="{(_at_)name}">
    <xsl:choose>
      <xsl:when test="../obj[(_at_)name = $child]">
        <xsl:apply-templates select="../obj[(_at_)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="{(_at_)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(_at_)saxonica(_dot_)com> 
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

--~------------------------------------------------------------------
XSL-List info and archive:  http://www.mulberrytech.com/xsl/xsl-list
To unsubscribe, go to: http://lists.mulberrytech.com/xsl-list/
or e-mail: <mailto:xsl-list-unsubscribe(_at_)lists(_dot_)mulberrytech(_dot_)com>
--~--