Re: Binary output method

Hello XSLT 1.1 Editors,

This is in response to a posting I found by Peter Ciuffetti dated Fri, 16 
Feb 2001.
I enjoyed writing this. I hope it is still needed 20 months after the fact.

Dylan Doxey
dylan@doxey.org


============================================================================ 
====
============================================================================ 
====


<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="html" indent="yes"/>

<!--
	decode64 will convert an arbitrary length base64 string to the ASCII 
character form.
	It is limited to printable ASCII characters on the range of 32 to 127.
	Author: Dylan Doxey - dylan@doxey.org
	Date: October 18, 2002
	Credit: Idea and "ctoi" section go to Pete Ciuffetti
-->


<!-- This accepts a base64 string of arbitray length and translates it to 
an ASCII character string. -->
<xsl:template name="decode64">
	<xsl:param name="b64string"/>
	<xsl:variable name="padding">===</xsl:variable>
	<!-- Ensure that the lenght of the input is a multiple of 4. -->
	<xsl:variable name="b64stringPadded" select="concat($b64string, 
substring($padding, 1, (string-length($b64string) mod 4)))"/>
	<!-- Take the first four b64 characters -->
	<xsl:variable name="b64quad" select="substring($b64stringPadded, 1, 4)"/>
	<!-- create a binary string representing the first three ASCII characters -->
	<xsl:variable name="binaryTrio">
		<xsl:call-template name="base642binary">
			<xsl:with-param name="b64quad" select="$b64quad"/>
		</xsl:call-template>
	</xsl:variable>
	<!-- Convert the three bytes to ASCII characters -->
	<xsl:call-template name="bytes2ascii">
		<xsl:with-param name="bytes" select="$binaryTrio"/>
	</xsl:call-template>
	<!-- If there are additional base64 characters to be decoded then recurse. -->
	<xsl:if test="string-length($b64stringPadded) &gt; 4">
		<xsl:call-template name="decode64">
			<xsl:with-param name="b64string" select="substring($b64stringPadded, 5)"/>
		</xsl:call-template>
	</xsl:if>
</xsl:template>

<!-- This will convert three bytes of binary to the appropriate three ASCII 
characters -->
<xsl:template name="bytes2ascii">
	<xsl:param name="bytes"/>
		<xsl:variable name="ascii1">
			<xsl:call-template name="byte2ascii">
				<xsl:with-param name="byte" select="substring($bytes, 1, 8)"/>
				<xsl:with-param name="factor" select="128"/>
			</xsl:call-template>
		</xsl:variable>
		<xsl:variable name="ascii2">
			<xsl:call-template name="byte2ascii">
				<xsl:with-param name="byte" select="substring($bytes, 9, 8)"/>
				<xsl:with-param name="factor" select="128"/>
			</xsl:call-template>
		</xsl:variable>
		<xsl:variable name="ascii3">
			<xsl:call-template name="byte2ascii">
				<xsl:with-param name="byte" select="substring($bytes, 17, 8)"/>
				<xsl:with-param name="factor" select="128"/>
			</xsl:call-template>
		</xsl:variable>
		<xsl:call-template name="ascii2char">
			<xsl:with-param name="ascii" select="$ascii1"/>
		</xsl:call-template>
		<xsl:call-template name="ascii2char">
			<xsl:with-param name="ascii" select="$ascii2"/>
		</xsl:call-template>
		<xsl:call-template name="ascii2char">
			<xsl:with-param name="ascii" select="$ascii3"/>
		</xsl:call-template>
		<!-- xsl:value-of select="$ascii1"/>-<xsl:value-of 
select="$ascii2"/>-<xsl:value-of select="$ascii3"/ -->
</xsl:template>

<!-- This will convert an arbitrary length binary number to decimal. For 
this application it is assumed to be one byte. -->
<xsl:template name="byte2ascii">
	<!-- The binary input -->
	<xsl:param name="byte"/>
	<!-- This is the factor of 2 for the most significant digit -->
	<xsl:param name="factor"/>
	<!-- Calculate the value of the most significant binary digit -->
	<xsl:variable name="first" select="substring($byte, 1, 1) * $factor"/>
	<!-- Recurse to calculate the value of any remaining digits -->
	<xsl:variable name="rest">
		<xsl:choose>
			<xsl:when test="$factor &gt; 1">
				<xsl:call-template name="byte2ascii">
					<xsl:with-param name="byte" select="substring($byte, 2)"/>
					<xsl:with-param name="factor" select="$factor div 2"/>
				</xsl:call-template>
			</xsl:when>
			<!-- xsl:otherwise><xsl:value-of select="substring($byte, 1, 1) * 
$factor"/></xsl:otherwise -->
			<xsl:otherwise>0</xsl:otherwise>
		</xsl:choose>
	</xsl:variable>
	<!-- Display the result -->
	<xsl:value-of select="$first + $rest"/>
</xsl:template>

<!-- Translate a decimal on the range of 32 to 127 to an ASCII character. -->
<xsl:template name="ascii2char">
	<xsl:param name="ascii"/>
	<xsl:variable name="asciiIndex" select="$ascii - 31"/>
	<xsl:variable name="ascii32to126"> 
!"#$%&amp;'()*+,-./0123456789:;&lt;=&gt;?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`ab 
cdefghijklmnopqrstuvwxyz{|}~</xsl:variable>
	<xsl:value-of select="substring($ascii32to126, $asciiIndex, 1)"/>
</xsl:template>

<!-- Translate an arbitrary length string of base64 characters to binary. 
For this application it is assumed to be four characters at a time. -->
<xsl:template name="base642binary">
	<xsl:param name="b64quad"/>
	<!-- Get the 0-63 value of the first character -->
	<xsl:variable name="octet">
		<xsl:call-template name="ctoi">
			<xsl:with-param name="c" select="substring($b64quad, 1, 1)"/>
		</xsl:call-template>
	</xsl:variable>
	<!-- Gather a six bit (octal) binary number for this character -->
	<xsl:variable name="binary">
		<xsl:call-template name="oct2bin">
			<xsl:with-param name="octal" select="$octet"/>
			<xsl:with-param name="order" select="6"/>
		</xsl:call-template>
	</xsl:variable>
	<!-- display the binary conversion -->
	<xsl:value-of select="$binary"/>
	<!-- recurse for the remaining digits -->
	<xsl:if test="string-length($b64quad) &gt; 1">
		<xsl:call-template name="base642binary">
			<xsl:with-param name="b64quad" select="substring($b64quad, 2)"/>
		</xsl:call-template>
	</xsl:if>
</xsl:template>

<!-- Translate an octal number to its six bit binary form. -->
<xsl:template name="oct2bin">
	<xsl:param name="octal"/>
	<xsl:param name="order"/>
	<xsl:variable name="last"><xsl:value-of select="$octal mod 2"/></xsl:variable>
	<xsl:variable name="rest"><xsl:value-of select="floor($octal div 
2)"/></xsl:variable>
	<xsl:if test="$order &gt; 1">
		<xsl:call-template name="oct2bin">
			<xsl:with-param name="octal" select="$rest"/>
			<xsl:with-param name="order" select="$order - 1"/>
		</xsl:call-template>
	</xsl:if>
	<xsl:choose>
		<xsl:when test="$last != -1"><xsl:value-of select="$last"/></xsl:when>
		<xsl:otherwise>0</xsl:otherwise>
	</xsl:choose>
</xsl:template>

<!-- Convert a base64 Character to an integer via table lookup -->
<xsl:template name="ctoi">
<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:otherwise>-1</xsl:otherwise>
	</xsl:choose>
</xsl:template>

</xsl:stylesheet>

Received on Friday, 18 October 2002 12:40:02 UTC