W3C home > Mailing lists > Public > xsl-editors@w3.org > January to March 2001

Binary output method?

From: Peter Ciuffetti <PeterC@acunet.net>
Date: Fri, 16 Feb 2001 11:06:17 -0500 (EST)
Message-ID: <3A8D500D.1FDEE7A8@acunet.net>
To: xsl-editors@w3.org
Hello XSLT 1.1 Editors,

Given the predominance of the use of base64 encoding to store binary
imagas and such in XML documents, I would find it useful to have an
output method 'binary' that would instruct an XSLT processor to output
binary octets (instead of always outputing characters).  With the new
capability to output multple result documents, it would then be
conceivable to store a mixed-media document in XML and then in one pass
generate the HTML, the multi-media files and the HTML links to these for
presentation to user agents.

Here's how it could work:

1. Add a output method="binary" to xsl:output and xsl:document,
2. Allow a new number formatter called xsl:binary-number.  This
top-level element would establish the base and possibly whether the
result was big-endian or little-endian.
3. Add a new function called format-binary(number, string, string) that
would format the integer according to the binary number formatter.

Thanks,
Pete Ciuffetti

P.S.
If these features existed, then a complete example for decoding base64
would look like this:

<xsl:stylesheet version="1.1"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

<xsl:output method="binary" indent="no" omit-xml-declaration="yes"/>

<!-- Match a base64 encoded element -->
<xsl:template match="base64">
    <!-- First, take out any of the white space in a base64-encoded
element -->
    <xsl:variable name="normalized">
       <xsl:call-template name="stripWhite">
          <xsl:with-param name="theText" select="."/>
       </xsl:call-template>
    </xsl:variable>
    <!-- Then decode the base 64 element, outputing binary octets -->
    <xsl:call-template name="decodeBase64">
        <xsl:with-param name="theText" select="$normalized"/>
    </xsl:call-template>
</xsl:template>

<!-- A named template to decode a base64 string -->
<xsl:template name="decodeBase64">
<xsl:param name="theText"/>
    <!-- Grab four characters to decode. If necessary, pad with '=' to
make 4 characters -->
    <xsl:choose>
        <xsl:when test="string-length($theText) &gt; 4">
            <xsl:call-template name="decodeBase64Chunk">
                <xsl:with-param name="theChunk"
select="substring($theText,1,4)"/>
            </xsl:call-template>
            <xsl:call-template name="decodeBase64">
                <xsl:with-param name="theText"
select="substring($theText,5)"/>
            </xsl:call-template>
        </xsl:when>
        <xsl:when test="string-length($theText) = 4">
            <xsl:call-template name="decodeBase64Chunk">
                <xsl:with-param name="theChunk" select="$theText"/>
            </xsl:call-template>
        </xsl:when>
        <xsl:when test="string-length($theText) = 3">
            <xsl:call-template name="decodeBase64Chunk">
                <xsl:with-param name="theChunk"
select="concat($theText,'=')"/>
            </xsl:call-template>
        </xsl:when>
        <xsl:when test="string-length($theText) = 2">
            <xsl:call-template name="decodeBase64Chunk">
                <xsl:with-param name="theChunk"
select="concat($theText,'==')"/>
            </xsl:call-template>
        </xsl:when>
        <xsl:when test="string-length($theText) = 1">
            <xsl:call-template name="decodeBase64Chunk">
                <xsl:with-param name="theChunk"
select="concat($theText,'===')"/>
            </xsl:call-template>
        </xsl:when>
     </xsl:choose>
</xsl:template>

<!-- Decode a 4-character base64 chunk, converting the characters to
hexadecimal integers -->
<xsl:template name="decodeBase64Chunk">
<xsl:param name="theChunk"/>

<!-- Isolate each character in the 4-character chunk and convert the
characters to character integers -->
<xsl:variable name="i1">
   <xsl:call-template name="ctoi">
      <xsl:with-param name="c" select="substring($theChunk,1,1)"/>
   </xsl:call-template>
</xsl:variable>
<xsl:variable name="i2">
   <xsl:call-template name="ctoi">
      <xsl:with-param name="c" select="substring($theChunk,2,1)"/>
   </xsl:call-template>
</xsl:variable>
<xsl:variable name="i3">
   <xsl:call-template name="ctoi">
      <xsl:with-param name="c" select="substring($theChunk,3,1)"/>
   </xsl:call-template>
</xsl:variable>
<xsl:variable name="i4">
   <xsl:call-template name="ctoi">
      <xsl:with-param name="c" select="substring($theChunk,4,1)"/>
   </xsl:call-template>
</xsl:variable>

<!-- Calculate the integer value of each output character -->
<xsl:variable name="o1" select="(($i1 * 4) + ($i2 div 16)) mod 256"/>
<xsl:variable name="o2" select="(($i2 * 16) + ($i3 div 4)) mod 256"/>
<xsl:variable name="o3" select="(($i3 * 64) + $i4) mod 256"/>

<!- Now use binary-format to output hexadecimal octets -->
<xsl:value-of select="format-binary($o1,'#','hex')"/><xsl:value-of
select="format-binary($o2,'#','hex')"/><xsl:value-of
select="format-binary($o3,'#','hex')"/>.
</xsl:template>

<xsl:binary-format name="hex" base="256"/>

<xsl:template name="ctoi">
<!-- Convert a base64 Character to an integer via table lookup -->
<xsl:param name="c"/>
<xsl:choose>
   <xsl:when test="$c = 'A'">0</xsl:when>
   <xsl:when test="$c = 'B'">1</xsl:when>
   <xsl:when test="$c = 'C'">2</xsl:when>
   <xsl:when test="$c = 'D'">3</xsl:when>
   <xsl:when test="$c = 'E'">4</xsl:when>
   <xsl:when test="$c = 'F'">5</xsl:when>
   <xsl:when test="$c = 'G'">6</xsl:when>
   <xsl:when test="$c = 'H'">7</xsl:when>
   <xsl:when test="$c = 'I'">8</xsl:when>
   <xsl:when test="$c = 'J'">9</xsl:when>
   <xsl:when test="$c = 'K'">10</xsl:when>
   <xsl:when test="$c = 'L'">11</xsl:when>
   <xsl:when test="$c = 'M'">12</xsl:when>
   <xsl:when test="$c = 'N'">13</xsl:when>
   <xsl:when test="$c = 'O'">14</xsl:when>
   <xsl:when test="$c = 'P'">15</xsl:when>
   <xsl:when test="$c = 'Q'">16</xsl:when>
   <xsl:when test="$c = 'R'">17</xsl:when>
   <xsl:when test="$c = 'S'">18</xsl:when>
   <xsl:when test="$c = 'T'">19</xsl:when>
   <xsl:when test="$c = 'U'">20</xsl:when>
   <xsl:when test="$c = 'V'">21</xsl:when>
   <xsl:when test="$c = 'W'">22</xsl:when>
   <xsl:when test="$c = 'X'">23</xsl:when>
   <xsl:when test="$c = 'Y'">24</xsl:when>
   <xsl:when test="$c = 'Z'">25</xsl:when>

   <xsl:when test="$c = 'a'">26</xsl:when>
   <xsl:when test="$c = 'b'">27</xsl:when>
   <xsl:when test="$c = 'c'">28</xsl:when>
   <xsl:when test="$c = 'd'">29</xsl:when>
   <xsl:when test="$c = 'e'">30</xsl:when>
   <xsl:when test="$c = 'f'">31</xsl:when>
   <xsl:when test="$c = 'g'">32</xsl:when>
   <xsl:when test="$c = 'h'">33</xsl:when>
   <xsl:when test="$c = 'i'">34</xsl:when>
   <xsl:when test="$c = 'j'">35</xsl:when>
   <xsl:when test="$c = 'k'">36</xsl:when>
   <xsl:when test="$c = 'l'">37</xsl:when>
   <xsl:when test="$c = 'm'">38</xsl:when>
   <xsl:when test="$c = 'n'">39</xsl:when>
   <xsl:when test="$c = 'o'">40</xsl:when>
   <xsl:when test="$c = 'p'">41</xsl:when>
   <xsl:when test="$c = 'q'">42</xsl:when>
   <xsl:when test="$c = 'r'">43</xsl:when>
   <xsl:when test="$c = 's'">44</xsl:when>
   <xsl:when test="$c = 't'">45</xsl:when>
   <xsl:when test="$c = 'u'">46</xsl:when>
   <xsl:when test="$c = 'v'">47</xsl:when>
   <xsl:when test="$c = 'w'">48</xsl:when>
   <xsl:when test="$c = 'x'">49</xsl:when>
   <xsl:when test="$c = 'y'">50</xsl:when>
   <xsl:when test="$c = 'z'">51</xsl:when>

   <xsl:when test="$c = '0'">52</xsl:when>
   <xsl:when test="$c = '1'">53</xsl:when>
   <xsl:when test="$c = '2'">54</xsl:when>
   <xsl:when test="$c = '3'">55</xsl:when>
   <xsl:when test="$c = '4'">56</xsl:when>
   <xsl:when test="$c = '5'">57</xsl:when>
   <xsl:when test="$c = '6'">58</xsl:when>
   <xsl:when test="$c = '7'">59</xsl:when>
   <xsl:when test="$c = '8'">60</xsl:when>
   <xsl:when test="$c = '9'">61</xsl:when>

   <xsl:when test="$c = '+'">62</xsl:when>
   <xsl:when test="$c = '/'">63</xsl:when>
</xsl:choose>
</xsl:template>

<xsl:template name="stripWhite">
<!-- Delete any white space in a base 64 string -->
<xsl:param name="theText"/>
   <xsl:if test="string-length($theText) &gt;= 1 and
string-length(normalize-space(substring($theText, 1, 1)))">
      <xsl:value-of select="substring($theText,1,1)"/>
   </xsl:if>
   <xsl:if test="string-length($theText) &gt; 1">
      <xsl:call-template name="stripWhite">
         <xsl:with-param name="theText" select="substring($theText,2)"/>

      </xsl:call-template>
   </xsl:if>
</xsl:template>

</xsl:stylesheet>
Received on Friday, 16 February 2001 11:51:29 GMT

This archive was generated by hypermail 2.2.0+W3C-0.50 : Monday, 7 December 2009 10:59:52 GMT