Re: [xsl] combining property lists with content

Subject: Re: [xsl] combining property lists with content
From: Jeni Tennison <jeni@xxxxxxxxxxxxxxxx>
Date: Tue, 22 Jan 2002 17:48:11 +0000
Hi Siri,

> At the moment I am using a series of for-each statements to lay out
> first all the text, then all the roots, etc. because I can't build
> the table column by column, and if I use one cell with a new table
> inside for each word I found that the rows don't line up evenly.
> This works, but I find using 8 consecutive for-each statements with
> just the property name changed excessively crude. Can anyone suggest
> a more efficient and more elegant way to go about this?

The first step, I think, is to cut down the repeated code by having a
single template with a parameter to change the details rather than a
number of xsl:for-each elements. I'd use a template that matches text
elements, with a parameter that indicates the type of row that you
want to create, with a keyword (perhaps the name of the relevant
property within the def element). Something like:

<xsl:template match="text">
  <xsl:param name="property" />
  <td>
    <xsl:choose>
      <xsl:when test="$property">
        <xsl:variable name="defid" select="@defid" />
        <xsl:value-of select="$lexicon/d_lst/def[@id = $defid]
                                /*[name() = $property]" />
      </xsl:when>
      <xsl:otherwise><xsl:value-of select="." /></xsl:otherwise>
    </xsl:choose>
  </td>
</xsl:template>

[Note that not passing in a value for the $property parameter means
that you get the value of the text element itself.]

You could call these by applying templates to the text elements with
the appropriate value for the $property parameter, once per row:

  <tr>
    <xsl:apply-templates select="text" />
  </tr>
  <tr>
    <xsl:apply-templates select="text">
      <xsl:with-param name="property" select="'property1'" />
    </xsl:apply-templates>
  </tr>

Of course you could turn that into a (named) template for creating a
row, something like:

<xsl:template name="createRow">
  <xsl:param name="property" />
  <tr>
    <xsl:apply-templates select="text">
      <xsl:with-param name="property" select="$property" />
    </xsl:apply-templates>
  </tr>
</xsl:template>

Then all you'd have to do is:

  <xsl:call-template name="createRow" />
  <xsl:call-template name="createRow">
    <xsl:with-param name="property" select="'property1'" />
  </xsl:call-template>

To make it more efficient, I'd use a key that indexed all the property
elements within the lexicon by their parent def's id and by their
element name, to make it easier to get hold of the relevant value
quickly. The key would look like:

<xsl:key name="properties" match="def/*"
         use="concat(../@id, '+', name())" />

And then you could use the following within the text element-matching
template:

<xsl:template match="text">
  <xsl:param name="property" />
  <td>
    <xsl:choose>
      <xsl:when test="$property">
        <xsl:variable name="defid" select="@defid" />
        <xsl:for-each select="$lexicon">
          <xsl:value-of select="key('properties',
                                    concat($defid, '+', $property)" />
        </xsl:for-each>
      </xsl:when>
      <xsl:otherwise><xsl:value-of select="." /></xsl:otherwise>
    </xsl:choose>
  </td>
</xsl:template>

If you were prepared to use a node-set() extension function, another
approach would be to build a new tree that contained all the
information from the text and the lexicon, and then process that
repeatedly. I don't know whether it would end up being faster than
using the key as shown above - it probably depends on the size of your
lexicon and text documents to a certain extent - but it would be worth
trying out as an alternative to see.

(If we were on XSLT 2.0, I'd be tempted to collect the def elements
into a sequence and process that sequence, rather than processing the
sequence of text elements. This would give you the advantages of the
second method (you don't have to index into the same document to find
the same def elements over and over again), without the cost of
building a new result tree.)

Cheers,

Jeni

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


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


Current Thread