RE: RE: [xsl] How to implement an array

Subject: RE: RE: [xsl] How to implement an array
From: Wendell Piez <wapiez@xxxxxxxxxxxxxxxx>
Date: Wed, 12 Feb 2003 16:39:57 -0500
Imrran,

I was hoping you'd dig in the archive, or in the FAQ. You'll see some treatment in the FAQ under "Lookup": http://www.dpawson.co.uk/xsl/sect2/N4995.html. There is far more in the archive.

The basic technique relies on a feature of the document() function: passing it an empty string as an argument returns the root of the parsed stylesheet as a node set, which you can traverse. So if, for example, your stylesheet contains a bit like this:

<iw:year xmlns:iw="imrransnamespace.org">
  <month name="January"/>
  <month name="February"/>
  <month name="March"/>
  <month name="April"/>
  <month name="May"/>
  <month name="June"/>
  <month name="July"/>
  <month name="August"/>
  <month name="September"/>
  <month name="October"/>
  <month name="November"/>
  <month name="December"/>
</iw:year>

You can retrieve the month nodes as a node set by calling the XPath

document('')/*/iw:year/month

(Remember to declare the iw namespace in your stylesheet. And note the extra step in the XPath, to skip the xsl:stylesheet element. Also, there's no particular reason your lookup table *must* be in your stylesheet: that's just commonly convenient. Use the document() function as normal if it's somewhere else.)

Bind this node set to a variable:

<xsl:variable name="months" select="document('')/*/iw:year/month"/>

And now you have a node set you can traverse. So if your source has:

<events>
  <event date="February 22">Lincoln's Birthday</event>
  <event date="March 15">Ides of March</event>
</events>

You can do

<xsl:template match="events">
  <xsl:variable name="events" select="."/>
  <!-- bind the current node to a variable so we can get it back
       after we change context -->
  <tr>
    <xsl:for-each select="$months">
      <xsl:variable name="monthname" select="@name"/>
      <td>
        <xsl:choose>
          <xsl:when
             test="not($events/event[@date[contains(.,$monthname)]])">
            <xsl:text>&#160;</xsl:text><!-- nbsp -->
          </xsl:when>
          <xsl:otherwise>
            <xsl:apply-templates
                select="$events/event[@date[contains(.,$monthname)]]"/>
          </xsl:otherwise>
        </xsl:choose>
      </td>
    </xsl:for-each>
  </tr>
</xsl:template>

You get as many <td> elements as you have months -- every time. Any <event> elements that belong to that month, are processed in the <td> belonging to it.

Traversal and node retrieval can get a bit hairy when you start switching trees like this, so keep track of your context node. Key-based retrieval can help with this.

You can traverse the same list easily enough to generate your list of headers.

I hope this is enough to get you going. There is more in the list archives -- this is a near-FAQ.

Cheers,
Wendell

At 02:20 PM 2/12/2003, you wrote:
I am now posed with another challenge. How do I use an
external lookup table to define the column headings?
E.g. Jan, Feb, Mar,...,Dec. Any pointers would be
appreciated.

Imrran


======================================================================
Wendell Piez                            mailto:wapiez@xxxxxxxxxxxxxxxx
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



Current Thread