RE: [xsl] translate for partial uri-encoding?

Subject: RE: [xsl] translate for partial uri-encoding?
From: <Jarno.Elovirta@xxxxxxxxx>
Date: Thu, 9 Sep 2004 08:25:44 +0300
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[@char = substring($text, 1, 1)]">
          <xsl:text>%</xsl:text>
          <xsl:value-of select="$map[@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

Current Thread