This is the mail archive of the xsl-list@mulberrytech.com mailing list .


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

Displaying entries in a table vertically



Does it matter that the entries line up horizontally?

If not, there's a simple solution:  generate a table with three
columns and one row.  Each cell is a table of one column and as many
rows as you need to output one third of the elements.

If that's not good enough you need to process the data in the order
that it must appear in the output rather than the order it appears in
the input.

A few months ago I was working on something similar but in my case
each element of the input had attributes which explicitly said which
row and column of the table the element should go in.  I've included
the transform below in case it might be helpful.  My input data looked 
like

<?xml version="1.0" encoding="utf-8"?>
<!-- edited with XML Spy v3.5 NT (http://www.xmlspy.com) by Mark Nahabedian ((self)) -->
<!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">
		<amps>60</amps>
		<special>doubled</special>
		<description>heat pump</description>
	</circuit-breaker>
	<circuit-breaker column="1" row="3" height="1">
		<amps>15</amps>
		<description>upper stairs, back bdroom stereo outlet</description>
	</circuit-breaker>
	<circuit-breaker column="1" row="4" height="1">
		<amps>20</amps>
		<description>kitchen sink garbage disposer</description>
	</circuit-breaker>
	<circuit-breaker column="2" row="1" height="1">
		<amps>20</amps>
		<special>GFCI</special>
		<description>outlet of both bathrooms, back outdoor
		outlets, <b>possible intermittent ground fault in
		circuit</b></description>
	</circuit-breaker>
	<circuit-breaker column="2" row="2" height="1">
		<amps>15</amps>
		<description>laundry room and garage lights, lower
		stairs</description>
	</circuit-breaker>
	<circuit-breaker column="2" row="3" height="1">
		<amps>15</amps>
		<description/>
	</circuit-breaker>
</circuit-breaker-panel>

================================================================================

<?xml version='1.0' encoding='utf-8' ?>
<stylesheet version="1.0" 
        xmlns="http://www.w3.org/1999/XSL/Transform";
        xmlns:xsl="http://www.w3.org/1999/XSL/Transform";
        xmlns:svg="http://www.w3.org/2000/svg";
        xmlns:html="http://www.w3.org/1999/xhtml"; 
        xmlns:xlink="http://www.w3.org/1999/xlink"; 
        xmlns:fb="http://www.ai.mit.edu/people/naha/XML-namespaces/fuse-box"; 
        exclude-result-prefixes="html svg">

    <!-- Currently only 'html' is supported -->
    <param name="output-type" select=" 'html' "/>

    <!--
	Some day need to figure out how to get this stuff in the output:
        PUBLIC: "-//W3C//DTD XHTML Basic 1.0//EN"
        SYSTEM: "http://www.w3.org/TR/xhtml-basic/xhtml-basic10.dtd";
    -->
    <output method="html" indent="yes" encoding="US-ASCII" standalone="no"/>

    <!-- It doesn't really matter what these nodes are.  We only get their positions. 
         They must be sequential though.  This is a well known XSLT pattern.
         It would be better to use nodes from the input document than from this XSLT
         document because we can be sure it will have enough nodes, but I don't
         know how to get its URI.  It would presumably be the base URI of any input
         document node.
     -->
    <variable name="random-nodes" select="//node()"/>
    <!-- The named template cb-max-row-and-column uses this string between the two values
          it returns to separate them.  -->
    <variable name="value-separator" select=" '---' "/>

    <template match="/">
        <choose>
            <when test=" $output-type = 'html' ">
                <html:html>
                    <apply-templates mode="html"/>
                </html:html>
            </when>
            <otherwise>
                <message>
                    <value-of select="$output-type"/>
                    <text>is not a supported output type.</text>
                </message>
            </otherwise>
        </choose>
    </template>

    <!-- ************************* HTML specific templates ******************************** -->

    <template match="fb:circuit-breaker-panel" mode="html">
        <variable name="this-panel-breakers" select="fb:circuit-breaker"/>
        <variable name="max-row-and-column">
            <call-template name="cb-max-row-and-column">
                <with-param name="circuit-breakers" select="fb:circuit-breaker"/>
            </call-template>
        </variable>
        <variable name="MaxRows"
                  select="substring-before($max-row-and-column, $value-separator)"/>
        <variable name="MaxColumns"
                  select="substring-after($max-row-and-column, $value-separator)"/>
        <if test="(count($random-nodes) &lt; $MaxRows) or
	          (count($random-nodes) &lt; $MaxColumns)">
            <message>
                <text>Not enough random nodes.  Some data will be lost in the output.</text>
            </message>
        </if>
        <variable name="html-column-width" select="100 div $MaxColumns"/>
        <variable name="html-row-height" select="100 div $MaxRows"/>
        <html:table border="1">
            <for-each select="$random-nodes[position() &lt;= $MaxRows]">
                <variable name="this-row" select="position()"/>
                <comment>
                    <text>Circuit Breaker: row number </text>
                    <value-of select="$this-row"/>
                </comment>
                <html:tr height="{$html-row-height}%">
                    <for-each select="$random-nodes[position() &lt;= $MaxColumns]">
                        <variable name="this-column" select="position()"/>
                        <comment>
                            <text> Circuit Breaker: </text>
                            <text>row number </text>
                            <value-of select="$this-row"/>
                            <text>, column number </text>
                            <value-of select="$this-column"/>
                            <text> </text>
                        </comment>
                        <variable name="column-breakers"
				  select="$this-panel-breakers[@column=$this-column]"/>
                        <variable name="this-circuit-breaker"
				  select="$column-breakers[@row=$this-row]"/>
                        <variable name="overlap-breakers"
				  select="$column-breakers[(@row &lt; $this-row)
                                          and (@row+@height) &gt; $this-row]"/>
                        <choose>
                            <!-- Several circuit breakers at same location -->
                            <when test="(count($this-circuit-breaker) +
					 count($overlap-breakers))
					&gt; 1">
                                <message>
                                    <text>Multiple circuit breakers at</text>
                                    <text>row =</text>
                                    <value-of select="$this-row"/>
                                    <text>column =</text>
                                    <value-of select="$this-column"/>
                                </message>
                                <comment>
                                    <text>Multiple circuit breakers</text>
                                    <value-of select="count($this-circuit-breaker)"/>
                                    <text>,</text>
                                    <value-of select="count($overlap-breakers)"/>
                                </comment>
                            </when>
                            <!-- No circuit breaker here but previous one in this column spans this row -->
                            <when test="$overlap-breakers[position() = 1]">
                                <comment>
                                    <text>Previous circuit breaker colspan's this row</text>
                                </comment>
                            </when>
                            <!-- Display this circuit breaker -->
                            <when test="$this-circuit-breaker[position() = 1]">
                                <for-each select="$this-circuit-breaker[position() = 1]">
                                    <html:td width="{$html-column-width}%" rowspan="{@height}">
                                        <apply-templates select="." mode="html"/>
                                    </html:td>
                                </for-each>
                            </when>
                            <!-- Empty position, placeholder cell -->
                            <otherwise>
                                <html:td bgcolor="silver">
                                    <comment>
                                        <text>Placeholder cell.  No circuit breaker in this position.</text>
                                    </comment>
                                    <html:pre> </html:pre>
                                </html:td>
                            </otherwise>
                        </choose>
                    </for-each>
                </html:tr>
            </for-each>
        </html:table>
    </template>

    <template match="fb:circuit-breaker" mode="html">
        <html:table border="0" height="100%" width="100%">
            <html:tr>
                <html:th width="10%">
                    <value-of select="fb:amps"/>
                    <if test="fb:special">
                        <html:br/>
                        <value-of select="fb:special"/>
                    </if>
                </html:th>
                <html:td>
                    <value-of select="fb:description"/>
                </html:td>
            </html:tr>
        </html:table>
    </template>

    <!-- ************************ named "subroutine" templates ******************************* -->
    <!-- the named template cb-max-row-and-column looks at all of the "circuit-breaker"
          elements in a given "circuit-breaker-panel" element and determines the maximum
          values of the "row" and "column" attributes.
    Call prototype:
    <call-template name="cb-max-row-and-column">
        <with-param name="circuit-breakers"/>
    </call-template>
    -->

    <template name="cb-max-row-and-column">
        <param name="previous-max-row" select="0"/>
        <param name="previous-max-column" select="0"/>
        <param name="circuit-breakers"/>
        <choose>
            <when test="boolean($circuit-breakers)">
                <variable name="this-circuit-breaker" 
                          select="$circuit-breakers[position()=1]"/>
                <variable name="this-cb-last-row"
                          select="$this-circuit-breaker/@row +
				  $this-circuit-breaker/@height - 1"/>
                <variable name="new-max-row">
                    <choose>
                        <when test="$this-cb-last-row &gt; $previous-max-row">
                            <value-of select="$this-cb-last-row"/>
                        </when>
                        <otherwise>
                            <value-of select="$previous-max-row"/>
                        </otherwise>
                    </choose>
                </variable>
                <variable name="new-max-column">
                    <choose>
                        <when test="$this-circuit-breaker/@column &gt; $previous-max-column">
                            <value-of select="$this-circuit-breaker/@column"/>
                        </when>
                        <otherwise>
                            <value-of select="$previous-max-column"/>
                        </otherwise>
                    </choose>
                </variable>
                <call-template name="cb-max-row-and-column">
                    <with-param name="previous-max-row"
				select="$new-max-row"/>
                    <with-param name="previous-max-column"
				select="$new-max-column"/>
                    <with-param name="circuit-breakers"
				select="$circuit-breakers[position() &gt; 1]"/>
                </call-template>
            </when>
            <otherwise>
                <!--
                can't return multiple values as a result tree fragment because the prcessor
                doesn't know how to treat such as anything other than a string.
                <element name="result">
                    <attribute name="max-row">
                        <value-of select="$previous-max-row"/>
                    </attribute>
                    <attribute name="max-column">
                        <value-of select="$previous-max-column"/>
                    </attribute>
                </element>
                -->
                <value-of select="$previous-max-row"/>
                <value-of select="$value-separator"/>
                <value-of select="$previous-max-column"/>
            </otherwise>
        </choose>
    </template>
</stylesheet>



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


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]