[XSL-LIST Mailing List Archive Home] [By Thread] [By Date]

[xsl] Term/Definition Lookup


Subject: [xsl] Term/Definition Lookup
From: "Rick Quatro rick@xxxxxxxxxxxxxx" <xsl-list-service@xxxxxxxxxxxxxxxxxxxxxx>
Date: Wed, 11 Jun 2014 19:01:33 -0000

Hi,

I have a comma-separated list of "terms". I want to loop through each term
and end up with a comma-separated list of definitions. I am using XSLT 1.0.
Here is my xml:

<?xml version="1.0" encoding="UTF-8"?>
<root>
    <terms>A, B, C, D, E</terms>
    <lookup>
        <term>A</term>
        <def>Def for A</def>
        <term>B</term>
        <def>Def for B</def>
        <term>C</term>
        <def>Def for C</def>
        <term>D</term>
        <def>Def for D</def>
        <term>E</term>
        <def>Def for E</def>
    </lookup>
</root>

The xml file has a built-in "lookup table" and here is the desired output:

<?xml version="1.0" encoding="UTF-8"?>
<root>
   <defs>Def for A, Def for B, Def for C, Def for D, Def for E</defs>
</root>

Here is my stylesheet:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    version="1.0">
    
    <xsl:output method="xml" indent="yes"/>
    
    <xsl:template match="/">
        <xsl:apply-templates/>
    </xsl:template>
    
    <xsl:template match="lookup"/>
    
    <xsl:template match="terms">
        <root>
            <defs>
                <xsl:call-template name="get-defs">
                    <xsl:with-param name="list" select="."/>
                </xsl:call-template>
            </defs>
        </root>
    </xsl:template>
    
    <xsl:template name="get-defs">
        <xsl:param name="list"/>
        <xsl:variable name="wlist"
select="concat(normalize-space(translate($list,',',' ')),' ')"/>
        <xsl:choose>
            <xsl:when test="$wlist!=' '">
                <xsl:variable name="first" select="substring-before($wlist,'
')"/>
                <xsl:variable name="rest" select="substring-after($wlist,'
')"/>
                <xsl:variable name="total">
                    <xsl:call-template name="get-defs">
                        <xsl:with-param name="list" select="$rest"/>
                    </xsl:call-template>
                </xsl:variable>
               <xsl:variable name="def">
                    <xsl:call-template name="get-def">
                        <xsl:with-param name="term" select="$first"/>
                    </xsl:call-template>
                </xsl:variable>
                <xsl:message><xsl:value-of select="$def"/></xsl:message>
                <xsl:choose>
                    <xsl:when test="$total=''">
                        <xsl:value-of select="$def"/>
                    </xsl:when>
                    <xsl:otherwise>
                        <xsl:value-of select="concat($def,', ',$total)"/>
                    </xsl:otherwise>
                </xsl:choose>
            </xsl:when>
        </xsl:choose>
    </xsl:template>
    
    <xsl:template name="get-def">
        <xsl:param name="term"/>
        <xsl:value-of select="//def[preceding-sibling::term=$term]"/>
    </xsl:template>
</xsl:stylesheet>

This works, but I have a couple of curiosities that I am trying to work
through. If I change one of the terms so that the "get-def" template doesn't
match (for example, "B" to "BB"), I get this:

<?xml version="1.0" encoding="UTF-8"?>
<root>
   <defs>Def for A, , Def for C, Def for D, Def for E</defs>
</root>

I thought I could use an <xsl:if test="$def!=''"> right before the last
<xsl:choose> statement, but when I do, I only get this:

<?xml version="1.0" encoding="UTF-8"?>
<root>
   <defs>Def for A</defs>
</root>

Once there is no match on "B" it short-circuits the rest of the list. Any
help or guidance would be appreciated. Thanks.

Rick Quatro

Rick Quatro
Carmen Publishing Inc.
585-366-4017
rick@xxxxxxxxxxxxxxx


Current Thread
Keywords