[xsl] lookup table (was: mixed content nodes question)

Subject: [xsl] lookup table (was: mixed content nodes question)
From: Kevin Rodgers <kevin.rodgers@xxxxxxx>
Date: Fri, 7 Jan 2005 15:44:44 -0700
Michael Kay writes:
> > > Or to one who doesn't like if's
> > >
> > ><xsl:template match="dictionary[lookup = '3']>Foo<xsl:/template>
> > ><xsl:template match="dictionary[lookup = '4']>Foo<xsl:/template>
> 
> My preferred way to do lookups is to make it table driven:
> 
> <xsl:variable name="table">
>   <entry code="3" value="foo"/>
>   <entry code="4" value="bar"/>
> </xsl:variable>
> 
> <xsl:template match="dictionary">
>   <xsl:value-of select="$table/entry[@code=current()/@lookup]/@value"/>
> </xsl:template>

I'm a novice working on my first stylesheet, which has a lookup table
that I implemented like this:

<xsl:template name="convert-language">
  <xsl:param name="code">en</xsl:param>
  <!-- See ISO 639 -->
  <xsl:choose>
    <xsl:when test="$code = 'ar'">ARABIC</xsl:when>
    <xsl:when test="$code = 'de'">GERMAN</xsl:when>
    <xsl:when test="$code = 'es'">SPANISH</xsl:when>
...
    <xsl:otherwise>
      <xsl:message terminate="no">Unrecognized language code: <xsl:value-of select="$code"/></xsl:message>
      <xsl:value-of select="$code"/>
    </xsl:otherwise>
  </xsl:choose>
</xsl:template>

That is accessed like this:

      <xsl:call-template name="convert-language">
        <xsl:with-param name="code"
           select="stringmb3e:doc_lang_list/mb3e:doc_lang[1]"/>
      </xsl:call-template>

Then I came across an element that had no mb3e:doc_lang_list child and
thus no mb3e:doc_lang grandchildren, which generated the "Unrecognized
language code" message (with no value for the allegedly erroneous code).
So I added this instruction before <xsl:otherwise> to simply return an
empty string in that case:

    <xsl:when test="$code = ''"></xsl:when>

I was surprised that (under Xalan 2.6.0) that didn't solve the problem
-- I still got the error message.  I got the desired behavior by
changing the call to this:

      <xsl:call-template name="convert-language">
        <xsl:with-param name="code"
           select="string(mb3e:doc_lang_list/mb3e:doc_lang[1])"/>
      </xsl:call-template>

But I obviously have a fundamental misunderstanding: I know that the
select expression in the original call returns a node-set, which the
XSLT processor apparently converts automatically to a string when
evaluating the test expression (as desired, since I get the intended
language names in my output).  So why doesn't the empty node-set match
the empty string test (i.e. why do I have to explicitly convert it
before calling the lookup template)?

> Needs the xx:node-set() extension or the document("") cheat if using XSLT
> 1.0.

I'd rather learn the ropes and get an XSLT 1.0 prototype working before
delving into XSLT 2.0.  What are the advantages of your implementation,
and what are the xx:node-set() extension and the document("") cheat?

Thanks,
-- 
Kevin Rodgers

Current Thread