xsl-list
[Top] [All Lists]

RE: recursion with xsl:apply-templates

2003-08-27 04:26:34
Firstly, the line 

       <xsl:apply-templates select="descendant::*"/>

looks wrong. This processes the descendants at each level; but at each
level a node is going to process its own children, so this is
unnecessary.

Secondly, you've left something out:

     <xsl:apply-templates select>

What was the value of the select attribute?

Finally, I don't see why you need recursion at all. I think the
following should do the job:

<xsl:template match="HEADER">
 ...
 <xsl:apply-templates select="*[(_at_)index]" mode="id"/>
</xsl:template>

<xsl:template match="*" mode="id">
  <xsl:copy>
  <xsl:copy-of select="@*[not(name()='index')]"/>
  <xsl:variable name="p" select="position()"/>
  <xsl:copy-of select="/transformation/id_list/id[$p]"/>
  <xsl:copy-of select="child::node()"/>
  </xsl:copy>
</xsl:template>

But this doesn't copy the elements without an @index attribute. If
that's a requirement, and if they have to be kept in their original
order, then you can't rely on position() in this way. But all is not
lost: instead of position(), use count(preceding::*[(_at_)index])+1.

Michael Kay

-----Original Message-----
From: owner-xsl-list(_at_)lists(_dot_)mulberrytech(_dot_)com 
[mailto:owner-xsl-list(_at_)lists(_dot_)mulberrytech(_dot_)com] On Behalf Of 
Volker Witzel
Sent: 27 August 2003 10:14
To: XSL-List(_at_)lists(_dot_)mulberrytech(_dot_)com
Subject: [xsl] recursion with xsl:apply-templates


Hi,

I have a problem with a recursion and I don't have a clue, why my 
solution does not work. I did not find anything on the web, 
so your help 
is greatly appreciated.

The problem:
I need to perform an XML to XML transformation to augment the 
data with 
unique keys.
The structure is as follows:
<transformation>
   <IRF>
     <HEADER>
       <REC_IR020_01 index="1">                       
         <UNB_S002_0004>16</UNB_S002_0004>
         ...
       </REC_IR020_01>
       <REC_IR030_01 index="1">
         <UNH_0062>03081402160553</UNH_0062>
         ...
       </REC_IR030_01>
      ...
   </IRF>
   <id_list>
     <id>2003-08-25 15:36:59.534096</id>
     ...
   </id_list>
</transformation>

I do not know all tag names, but I know that I have some 
elements with 
an index attribute, which I need to transform to
       <REC_IR020_01>                 
         <id>2003-08-25 15:36:59.534096</id>
         <UNB_S002_0004>16</UNB_S002_0004>
         ...
       </REC_IR020_01>
So I have to strip the index attribute and fetch one unique 
id from the 
id_list for each occurence of an index attribute.

My Solution:
I thought it's startightforward with XSL. My code:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"; 
xmlns:xalan="http://xml.apache.org/xslt";>
   <xsl:output method="xml" indent="yes" encoding="UTF-8" 
omit-xml-declaration="no" xalan:indent-amount="2" />
   <xsl:strip-space elements="*"/>
   <xsl:template match="/transformation">
     <xsl:apply-templates select="IRF"/>
   </xsl:template>
   <xsl:template match="IRF">
     <xsl:copy>
       <xsl:copy-of select="@*"/>
       <xsl:apply-templates select="descendant::*"/>
     </xsl:copy>
   </xsl:template>
   <xsl:template match="node()">
     <xsl:param name="idCount" select="1"/>
     <xsl:choose>
       <xsl:when test="@index">
         <xsl:copy>
           <xsl:element name="test"><xsl:value-of 
select="$idCount"/></xsl:element>
           <xsl:call-template name="addIdElement">
             <xsl:with-param name="idCount" select="$idCount"/>
           </xsl:call-template>
           <xsl:apply-templates select>
             <xsl:with-param name="idCount" select="$idCount + 1"/>
           </xsl:apply-templates>
         </xsl:copy>
       </xsl:when>
       <xsl:otherwise>
         <xsl:copy>
           <xsl:apply-templates>
             <xsl:with-param name="idCount" select="$idCount"/>
           </xsl:apply-templates>
         </xsl:copy>
       </xsl:otherwise>
     </xsl:choose>
   </xsl:template>
   <xsl:template name="addIdElement">
     <xsl:param name="idCount"/>
     <xsl:element name="id">
     <xsl:copy-of select="/transformation/id_list/id[$idCount]"/>
   </xsl:template>
</xsl:stylesheet>

My problem is that the lines
           <xsl:apply-templates select>
             <xsl:with-param name="idCount" select="$idCount + 1"/>
           </xsl:apply-templates>
do not call the template with the inceremnted parameter, so it always 
runs with the default value 1.

Any ideas where my brain is scrumbled?
Volker.



 XSL-List info and archive:  http://www.mulberrytech.com/xsl/xsl-list



 XSL-List info and archive:  http://www.mulberrytech.com/xsl/xsl-list