[xsl] ordering and iteration problem

Subject: [xsl] ordering and iteration problem
From: Mark Nahabedian <naha@xxxxxxxxxx>
Date: Thu, 26 Apr 2001 21:41:16 -0400 (EDT)
My source XML describes an electrical circuit breaker panel:

    <?xml version="1.0" encoding="utf-8" ?>
    <!DOCTYPE circuit-breaker-panel [
    <!ELEMENT circuit-breaker-panel (circuit-breaker)+>
    <!ELEMENT circuit-breaker (amps,special?,description)>
    <!ATTLIST circuit-breaker 
        column CDATA #REQUIRED 
        row CDATA #REQUIRED 
        height CDATA #IMPLIED >
    <!ELEMENT amps (#PCDATA)*>
    <!ELEMENT special (#PCDATA)*>
    <!ELEMENT description (#PCDATA)*>]>
    <circuit-breaker-panel xmlns="http://www.ai.mit.edu/people/naha/XML-namespaces/fuse-box";>
        <circuit-breaker column="1" row="1" height="2">
            <description>heat pump</description>
        <circuit-breaker column="1" row="3" height="1">
            <description>upper stairs</description>
        <circuit-breaker column="2" row="7" height="1">
        <circuit-breaker column="2" row="8" height="2">

For the sake of brevity I've edited out many of the <circuit-breaker>
elements.  The ones above are a representative sample.

The <circuit-breaker>s can appear in any order within the

My goal is a stylesheet that will transform such input into an HTML

I have a named template which will find the highest column number and
row number from all of the <circuit-breaker>s in the
<circuit-breaker-panel>, so I know what the highest column number and
row number will be.

To produce an HTML table, I need to generate each table row in order
based on the row numbers of the circuit breakers and then in numerical
column order generate a table cell for the <circuit-breaker> in that
row and column.  Note that it's possible for a single
<circuit-breaker> to occupy more than one sequential row in a given
column.  Just sorting the <circuit-breaker>s by row and column won't
work becaus ethere might be gaps in the panel.

My thinking is that I need to do something like

   for each row
       for each column
	   ooutput the <circuit-breaker> with that row and column

Since iterating over a range of integers is a useful abstraction, I've
written a named template which does do and calls another caller
specified named template for each such integer:

    <template name="do-integers">
        <param name="first-int" select="0"/>
        <param name="last-int"/>
        <param name="step" select="1"/>
        <param name="body-template-name"/>
        <param name="body-template-parameter-name"/>
        <if test="not($first-int &gt; $last-int)">
            <call-template name="$body-template-name">
                <with-param name="$body-template-parameter-name"
            <call-template name="do-integers">
                <with-param name="first-int" select="$first-int + $step"/>
                <with-param name="step" select="$step"/>
                <with-param name="last-int" select="$last-int"/>
                <with-param name="body-template-name" select="$body-template-name"/>
                <with-param name="body-template-parameter-name"

While basking in my presumed cleverness, I realized that this won't
work however because the "name" atrtributes of both <call-template>
and <with-param> must be qnames.  There's also the problem of not
being able to pass additional values from the template which calls
"do-integers" to the "body-template-name" template which it calls for
each iteration.  (Can you tell that I'm a Lisp programmer by trade?).

I could code the row and column iterations separatly but replicating
the code offends my sensibilities.  I'd rather write something more
general with broader applicability than have to recode the
functionality of "do-integers" with slight variation each time I need

Perhaps I'm approaching the problem in the wrong way but I don't see
another way of achieving the goal.  Any suggestions?

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

Current Thread