Re: [xsl] Apply template?

Subject: Re: [xsl] Apply template?
From: Abel Braaksma <abel.online@xxxxxxxxx>
Date: Wed, 16 May 2007 17:26:08 +0200
Here's one way to do it. But note that I had to guess about your input file. See below of what I tried as input.

<xsl:output indent="yes"/>

   <xsl:template match="B">
       <xsl:copy>
           <xsl:apply-templates select="@*" />
           <xsl:apply-templates select="C">
               <xsl:sort select="D" data-type="number" />
           </xsl:apply-templates>
       </xsl:copy>
   </xsl:template>

   <xsl:template match="@*|node()">
       <xsl:copy>
           <xsl:apply-templates select="@*|node()"/>
       </xsl:copy>
   </xsl:template>


A couple of things to notice:


1. Choosing xsl:for-each instead of xsl:apply-templates is like choosing between buckles or laces for your shoes. But to many people (including myself) it is also choosing between GOTO (1960) and FUNCTION (1970). But rest assured: xsl:for-each is a misguided xsl:apply-templates (and it is *not* a loop, contrary to its name).

2. There are situations where xsl:for-each is preferred, notably when the selection does not contain a sequence of nodes (you can't apply-templates on a sequence of strings.

3. You do not need to state that you want output of xml/utf-8/version 1.0, these are all the default.

4. You can apply an xsl:sort on for-each, for-each-group and apply-templates, no need to use for-each.

5. My approach does not do exactly the same as your approach. Depending on your real source data, it may need some tweaking.


It is good to learn about XSLT and about how to use xsl:apply-templates and matching templates. It will speed up your XSLT development dramatically once you get used to it. A good tutorial or a good teacher is usually all that it takes, and a few hours time of course. Once you get used to it, it is quite easy, really and you quickly forget about xsl:for-each.


Good luck coding,

Cheers,
-- Abel Braaksma

PS, this is the sample data I used:

<A>
   <B>
       <C name="x">
           <abc>some rubbish</abc>
           <D>5</D>
           <xyz>other rubbish here</xyz>
       </C>
       <C name="y">
           <abc>some rubbish</abc>
           <D>2</D>
           <xyz>other rubbish here</xyz>
       </C>
       <C name="z">
           <abc>some rubbish</abc>
           <D>12</D>
       </C>
       <C name="zz">
           <abc>some rubbish</abc>
           <D>3</D>
           <xyz>other rubbish here</xyz>
       </C>
   </B>
</A>




Danny Leblanc wrote:
Good day everyone,

I have read in the past here that most people who are not "used" to XSLT tend to use for-each when an apply template would be the better route. I have received the following XSLT file.

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform";>
  <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
  <xsl:template match="/">
    <A>
      <B>
         <xsl:for-each select="/A/B/C">
          <xsl:sort order = "ascending" data-type = "number" select = "D"/>
          <xsl:copy>
            <xsl:apply-templates select="@*|node()"/>
          </xsl:copy>
        </xsl:for-each>
      </B>
    </A>
  </xsl:template>
  <xsl:template match="@*|node()">
    <xsl:copy>
      <xsl:apply-templates select="@*|node()"/>
    </xsl:copy>
  </xsl:template>
</xsl:stylesheet>

In a case like this, would there be a better way to handle this using apply templates? Would there be a performance gain by using apply templates instead? I tried to put one together but to date have not had much success but just wanted to ensure that switching to apply templates would be the correct way to go.

Thank you for all advice given.

Danny

Current Thread