Jim,
Your problem is actually subtler than you may think it is. This isn't just
a matter of having multiple templates; it's that you are faced with an
"upconversion", which is to say you want to take advantage of information
that is only implicit in your source (in the values of nodes, specifically
your <Code> elements), and making it explicit in the node structure of your
output. In your case, the implicit information in the source is which
category goes inside which. You are going from a flat structure to a
nested, hierarchical one. Like many upconversions, it's essentially a
grouping problem.
Where possible, this kind of "levitation" (getting structure where there
was none) is best solved (in my experience) with keys, which are designed
to let you retrieve nodes based on associated values. Here, there are two
bits of information that are critical. One, to which level should a
category be assigned: this is indicated by the string length of its Code
child. Two, which category of the next level up does it belong with: this
is indicated by the value of the first n-1 characters of the Code, where n
is the Code's length. These two bits of logic can be encoded in keys like this:
<xsl:key name="level1" match="Category[string-length(Code)=1]"
use="'all'"/>
(This one is a convenience. It gets all the Categories A, B, C etc., as
long as their Code has one character. It returns them all with the key
value of 'all'.)
<xsl:key name="level2" match="Category[string-length(Code)=2]"
use="substring(Code, 1, 1)"/>
This one matches Categories AA, AB, DZ, FF etc, keying them to the values A
(for AA and AB), D, F etc.
<xsl:key name="level3" match="Category[string-length(Code)=3]"
use="substring(Code, 1, 2)"/>
Same, but matches AAA, AAC, DZC, FFF etc., keying them to AA, DZ, FF etc.
Then,
<xsl:template match="/">
<Categories>
<xsl:apply-templates select="key('level1','all')"/>
</Categories>
</xsl:template>
<xsl:template match="Category[string-length(Code)=1]">
<!-- matches only level 1 nodes -->
<LevelOneCategory Code="{Code}" Description="{Description}">
<xsl:apply-templates select="key('level2',Code)"/>
<!-- goes and gets the level 2 categories keyed to the value
of this one's Code -->
</LevelOneCategory>
</xsl:template>
<xsl:template match="Category[string-length(Code)=2]">
<!-- matches level 2 nodes -->
<LevelTwoCategory Code="{Code}" Description="{Description}">
<xsl:apply-templates select="key('level3',Code)"/>
<!-- goes and gets the level 3 categories keyed to the value
of this one's Code -->
</LevelTwoCategory>
</xsl:template>
<xsl:template match="Category[string-length(Code)=3]">
<!-- matches level 3 nodes -->
<LevelThreeCategory Code="{Code}" Description="{Description}"/>
</xsl:template>
Note that this method will be fast and efficient, but it requires you to
know in advance how deep your categories go (how many levels to allow for).
If this cannot be known until runtime, you have to use another technique
(and it'll be slower).
I hope that helps,
Wendell
At 03:25 PM 3/26/2003, you wrote:
Original:
<Categories>
<Category>
<Code>A</Code>
<Description>Airplanes</Description>
</Category>
<Category>
<Code>AA</Code>
<Description>Airplanes (ARF)</Description>
</Category>
<Category>
<Code>AAE</Code>
<Description>Airplanes (ARF), Electric</Description>
</Category>
<Category>
<Code>AAG</Code>
<Description>Airplanes (ARF), Giant</Description>
</Category>
<Category>
<Code>AAP</Code>
<Description>Airplanes (ARF), Sailplane</Description>
</Category>
<Category>
<Code>B</Code>
<Description>Boats</Description>
</Category>
<Category>
<Code>BA</Code>
<Description>Boats (ARF)</Description>
</Category>
<Category>
<Code>BAE</Code>
<Description>Boats (ARF), Electric</Description>
</Category>
<Categories>
Final Result - where one letter, two letter, and three letter categories are
nested.
<Categories>
<LevelOneCategory Code="A" Description="Airplanes">
<LevelTwoCategory Code="AA" Description="Airplanes (ARF)">
<LevelThreeCategory Code="AAE"
Description="Airplanes (ARF), Electric"/>
<LevelThreeCategory Code="AAG"
Description="Airplanes (ARF), Giant"/>
<LevelThreeCategory Code="AAP"
Description="Airplanes (ARF), Sailplane"/>
</LevelTwoCategory>
</LevelOneCategory>
<LevelOneCategory Code="B" Description="Boats">
<LevelTwoCategory Code="BA" Description="Boats (ARF)">
<LevelThreeCategory Code="BAE" Description="Boats
(ARF), Electric"/>
</LevelTwoCategory>
</LevelOneCategory>
<Categories>
======================================================================
Wendell Piez
mailto:wapiez(_at_)mulberrytech(_dot_)com
Mulberry Technologies, Inc. http://www.mulberrytech.com
17 West Jefferson Street Direct Phone: 301/315-9635
Suite 207 Phone: 301/315-9631
Rockville, MD 20850 Fax: 301/315-8285
----------------------------------------------------------------------
Mulberry Technologies: A Consultancy Specializing in SGML and XML
======================================================================
XSL-List info and archive: http://www.mulberrytech.com/xsl/xsl-list