Re: [xsl] XML to XML

Subject: Re: [xsl] XML to XML
From: Jeni Tennison <jeni@xxxxxxxxxxxxxxxx>
Date: Thu, 27 Mar 2003 09:37:52 +0000
Hi Jim,

> I need some help in writing xsl to transform XML to XML.
> I am getting lost in concepts of having multiple templates

You've had several solutions already. This is one that, like
Wendell's, uses keys, but this only uses one key, which makes it a bit
simpler.

First, index each <Category> element using all but the last letter of
its <Code> element child:

<xsl:key name="categories"
         match="Category"
         use="substring(Code, 1, string-length(Code) - 1)" />

When you use the function call:

  key('categories', 'A')

for example, you'll get every <Category> element whose <Code> element
has two letters and starts with an 'A'.

To start off, you want a template matching the <Categories> element to
apply templates to only those <Category> elements that have only one
letter codes; you can use the key to find these as they'll all be
indexed with the string '':

<xsl:template match="Categories">
  <Categories>
    <xsl:apply-templates select="key('categories', '')" />
  </Categories>
</xsl:template>

Then you can have a single template for all the <Category> elements.
This is a little complicated by the fact that you want to have
different element names for <Category> elements at different levels,
but basically it creates the relevant element, then applies templates
to those <Category> elements (using the key again) whose <Code> starts
with the <Code> of the <Category> element that you're processing:

<xsl:template match="Category">
  <xsl:variable name="level">
    <xsl:choose>
      <xsl:when test="string-length(Code) = 1">One</xsl:when>
      <xsl:when test="string-length(Code) = 2">Two</xsl:when>
      <xsl:when test="string-length(Code) = 3">Three</xsl:when>
      <xsl:otherwise>
        <xsl:message terminate="yes">
          I thought you said there'd only be three levels!
        </xsl:message>
      </xsl:otherwise>
    </xsl:choose>
  </xsl:variable>

  <xsl:element name="Level{$level}Category">
    <xsl:attribute name="Code">
      <xsl:value-of select="Code" />
    </xsl:attribute>
    <xsl:attribute name="Description">
      <xsl:value-of select="Description" />
    </xsl:attribute>
    <xsl:apply-templates select="key('categories', Code)" />
  </xsl:element>
</xsl:template>

Cheers,

Jeni

---
Jeni Tennison
http://www.jenitennison.com/


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


Current Thread