xsl-list
[Top] [All Lists]

RE: translate for partial uri-encoding?

2004-09-08 22:25:44
Hi,

Suppose I have this input document

<company>JOE'S PAINT &amp; BODY<company>

and I'm trying to insert the element's text in the query 
string of a URI in
a result document, doing something like this

<xsl:template match="/">
   <someURL>
       <xsl:text>xsl:text>http://foo.com/?X=1&amp;CO=</xsl:text>
       <xsl:value-of select="translate(/company, ' ', '+')"/>
    </someURL>
</xsl:template>

The result document should look like:
<someURL>http://foo.com/?X=1&amp;CO=JOE%27S+PAINT+%26+BODY</someURL>

The translate function arguments above are insufficient to correctly
url-encode the text of the input <company> node given above 
(as written, it
only converts space to +).  The proof-of-concept demo I'm 
producing in a
very limited time will run on an XSLT platform that does not 
support *any*
extensions (such as the EXSLT str:encode-uri), so I'm trying 
to get by with
xsl:translate.  For this demo, I have some control over what 
input will
actually be passed, but must at least appear to have some 
idea of what I'm
doing for common cases with unsafe characters.

What is the trick for including the ampersand and apostrophe 
characters in
the 2nd argument of the translate function and their encoded 
equivalents in
UTF-8 (e.g. %26 for the ampersand) in the third argument of 
translate? 

In pure XSLT, create a mapping table for all the characters you need to encode, 
something in the lines of

  <xsl:template match="/">
    <someURL>
      <xsl:text>http://foo.com/?X=1&amp;CO=</xsl:text>
      <xsl:call-template name="encode">
        <xsl:with-param name="text" select="translate(/company, ' ', '+')"/>
      </xsl:call-template>
    </someURL>
  </xsl:template>
  <xsl:template name="encode">
    <xsl:param name="text" select="''"/>
    <xsl:if test="$text">
      <xsl:choose>
        <xsl:when test="$map[(_at_)char = substring($text, 1, 1)]">
          <xsl:text>%</xsl:text>
          <xsl:value-of select="$map[(_at_)char = substring($text, 1, 
1)]/@code"/>
        </xsl:when>
        <xsl:otherwise>
          <xsl:value-of select="substring($text, 1, 1)"/>
        </xsl:otherwise>
      </xsl:choose>
      <xsl:call-template name="encode">
        <xsl:with-param name="text" select="substring($text, 2)"/>
      </xsl:call-template>
    </xsl:if>
  </xsl:template>
  <xsl:variable name="map" select="document('')/*/x:map/*"/>
  <x:map>
    <entry char="%" code="25"/>
    <entry char="&amp;" code="26"/>
    <entry char="'" code="27"/>
  </x:map>

Cheers,

Jarno - Dulce Liquido: Psychoanalytic


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