xsl-list
[Top] [All Lists]

Re: Join operation with a csv key in XSL?

2003-01-02 18:35:21
Hi,

Given the XML file:

<xml>
<info beforekey="a,b,c" afterkey="d,e">
  <details tag="a" path="t1.gif" />
  <details tag="b" path="t2.gif" />
  <details tag="c" path="t3.htm" />
  <details tag="d" path="t4.jpg" />
  <details tag="e" path="t5.doc" />
</info>
</xml>

I need to loop through the comma separated values of the 
beforekey and afterkey, grabbing the details records containing 
those keys, and putting them into img tags or a/href tags depending
on the extension (img tag for gif/jpg and a for the rest).

The easiest bit is generating the img/a elements from the details
elements based on the extension. The template should match details
elements and look at the letters after the . (or use some other
algorithm of your choice) to work out what to generate:

<xsl:template match="details">
  <xsl:variable name="ext"
                select="substring-after(@path, '.')" />
  <xsl:choose>
    <xsl:when test="$ext = 'gif' or $ext = 'jpg'">
      <img src="{(_at_)path}" />
    </xsl:when>
    <xsl:otherwise>
      <a href="{(_at_)path}" />
    </xsl:otherwise>
  </xsl:choose>
</xsl:template>

The harder part is working through the beforekey and afterkey
attributes to work out what to do. To do this, you need to create a
recursive template that works through the string, splitting it at
commas, and apply-templates to the details element that gets selected
for the particular 'tag'. I'd use a moded recursive template as
follows:

<xsl:template match="info" mode="show">
  <xsl:param name="tags" />
  <xsl:choose>
    <xsl:when test="contains($tags, ',')">
      <xsl:variable name="tag"
                    select="substring-before($tags, ',')" />
      <!-- show the details for the first tag -->
      <xsl:apply-templates select="details[(_at_)tag = $tag]" />
      <!-- recurse onto the rest of the tags -->
      <xsl:apply-templates select="." mode="show">
        <xsl:with-param name="tags"
                        select="substring-after($tags, ',')" />
      </xsl:apply-templates>
    </xsl:when>
    <xsl:when test="$tags">
      <!-- show details for the last listed tag -->
      <xsl:apply-templates select="details[(_at_)tag = $tags]" />
    </xsl:when>
  </xsl:choose>
</xsl:template>

To get the output that you're after, you need to invoke this template
twice, once with the value of beforekey as the value of the $tags
parameter, and once with the value of afterkey as the value of the
$tags parameter:

<xsl:template match="info">
  <html>
    Before:
    <xsl:apply-templates select="." mode="show">
      <xsl:with-param name="tags" select="@beforekey" />
    </xsl:apply-templates>
    After:
    <xsl:apply-templates select="." mode="show">
      <xsl:with-param name="tags" select="@afterkey" />
    </xsl:apply-templates>
  </html>
</xsl:template>

Cheers,

Jeni

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


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



<Prev in Thread] Current Thread [Next in Thread>