`
sunxboy
  • 浏览: 2879305 次
  • 性别: Icon_minigender_1
  • 来自: 武汉
社区版块
存档分类
最新评论

BASE64编解码之XSLT1.0实现

阅读更多

最近一直在研究BASE64编解码,偶然想到用XSLT来实现,在网络上搜索了半天,没有找到一篇相关的文章和说明。偶在O'REILLY的网站上看到有人求解,只见答复XSLT1.0无解,XSLT2.0才有相关方法函数,然而XSLT2.0的应用还不是很普遍。

熟悉XSLT&XPath的你一定知道,两者都没有相关方法函数可以取字符的ASCII值。而这一功能正是BASE64编解码的基本要素之一。

因为取不到ASCII值,用XSLT来实现BASE64编解码的想法几乎要放弃了。难道就这么放弃?这不是我的风格,我喜欢迎难而进!

受BASE64解码思想和之前自己用XSLT&XPath写的循环输出A-Z字符代码的启发,借助XPath中的几个字符串处理函数,终于实现了XSLT1.0环境下BASE64的编解码。

BASE64编码的原理就不再重复了,这里只附上wikipedia的BASE64编码的原理,同时介绍如何通过XSLT&XPath实现字符到“ASCII值”的转换原理:

基本的ASCII字符对应的ASCII为0-127,其中0-31、127共33个字符为控制字符,不可显示,32-126为可显示字符。据此,我们可以建立一个映射表,即“ !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~,”(注意:控制字符因为无法显示, 这里暂不考虑),其在映射表中的次序加上31即得到“ASCII值”。

附wikipedia的BASE64编码的原理:

转换的时候,将三个byte的数据,先后放入一个24bit的缓冲区中,先来的byte占高位。数据不足3byte的话,于缓冲区中剩下的Bit用0补足。然后,每次取出6个bit,按照其值选择ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/中的字符作为编码后的输出。不断进行,直到全部输入数据转换完成。
如果最后剩下两个输入数据,在编码结果后加1个「=」;如果最后剩下一个输入数据,编码结果后加2个「=」;如果没有剩下任何数据,就什么都不要加,这样才可以保证资料还原的正确性。

BASE64的解码实为编码的逆过程。

XSLT1.0实现BASE64编解码:

<?xml version="1.0" encoding="gb2312" ?> 

<!--Encoding&Decoding base64 with XSLT1.0--> 
<!--BASE64编解码之XSLT1.0实现--> 
<!--Author:Qr http://Qr.blogger.org.cn--> 
<!--Date:2009/06/29--> 

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> 
<xsl:output method="xml" encoding="gb2312" indent="yes"/> 
<xsl:output doctype-public="-//W3C//DTD XHTML 1.0 Strict//EN"/> 
<xsl:output doctype-system="http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"/> 

<xsl:variable name="CODEPAD" select="'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'"/> 
<xsl:variable name="ASCII"><![CDATA[ !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~,]]></xsl:variable> 

<!--原始字符串--> 
<xsl:variable name="CHAR" select="'Man is distinguished, not only by his reason, but by this singular passion from other animals, which is a lust of the mind, that by a perseverance of delight in the continued and indefatigable generation of knowledge, exceeds the short vehemence of any carnal pleasure.'"/> 
<!--原始字符串长度--> 
<xsl:param name="STRLENGTH" select="string-length($CHAR)"/> 
<!--循环次数--> 
<xsl:param name="CYCLE_CNT" select="floor($STRLENGTH div 3)"/> 
<!--模值--> 
<xsl:param name="MOD" select="$STRLENGTH mod 3"/> 

<!--待解码字符串--> 
<xsl:variable name="STR" select="'TWFuIGlzIGRpc3Rpbmd1aXNoZWQsIG5vdCBvbmx5IGJ5IGhpcyByZWFzb24sIGJ1dCBieSB0aGlzIHNpbmd1bGFyIHBhc3Npb24gZnJvbSBvdGhlciBhbmltYWxzLCB3aGljaCBpcyBhIGx1c3Qgb2YgdGhlIG1pbmQsIHRoYXQgYnkgYSBwZXJzZXZlcmFuY2Ugb2YgZGVsaWdodCBpbiB0aGUgY29udGludWVkIGFuZCBpbmRlZmF0aWdhYmxlIGdlbmVyYXRpb24gb2Yga25vd2xlZGdlLCBleGNlZWRzIHRoZSBzaG9ydCB2ZWhlbWVuY2Ugb2YgYW55IGNhcm5hbCBwbGVhc3VyZS4='"/> 
<!--待解码字符串长度--> 
<xsl:param name="STRLEN" select="string-length($STR)"/> 
<!--循环次数--> 
<xsl:param name="CYCLECNT" select="floor($STRLEN div 4)"/> 

<xsl:template match="/"> 
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="gb2312" lang="gb2312"> 
    <head> 
        <title>BASE64编解码之XSLT1.0实现 - Encoding&amp;Decoding base64 with XSLT1.0 by Qr</title> 
        <meta http-equiv="Content-Type" content="text/html; charset=gb2312" /> 
    </head> 
    <body> 
        <div style="margin:50px 168px;"> 
            <h1 style="text-align:center;">BASE64编解码之XSLT1.0实现</h1> 
            <xsl:text>原始字符串:[Thomas Hobbes's Leviathan文句]</xsl:text> 
            <textarea rows="6" cols="80" style="width:100%"> 
                <xsl:value-of select="$CHAR"/> 
            </textarea> 
            <xsl:text>编码字符串:</xsl:text> 
            <textarea rows="6" cols="80" style="width:100%"> 
                <xsl:call-template name="base64_encode"> 
                    <xsl:with-param name="number" select="1"/> 
                </xsl:call-template> 

                <xsl:if test="$MOD != 0"> 

                    <xsl:value-of select="substring($CODEPAD,floor((string-length(substring-before($ASCII,substring($CHAR,$CYCLE_CNT*3+1,1)))+1+31) div 4)+1,1)"/> 

                    <xsl:variable name="sec"> 
                        <xsl:choose> 
                        <xsl:when test="1=$MOD">0</xsl:when> 
                        <xsl:otherwise><xsl:value-of select="floor((string-length(substring-before($ASCII,substring($CHAR,$CYCLE_CNT*3+2,1)))+31) div 16)"/></xsl:otherwise> 
                        </xsl:choose> 
                    </xsl:variable> 
                    <xsl:value-of select="substring($CODEPAD,((string-length(substring-before($ASCII,substring($CHAR,$CYCLE_CNT*3+1,1)))+1+31) mod 4)*16+$sec+1,1)"/> 

                    <xsl:choose> 
                    <xsl:when test="1=$MOD"><xsl:value-of select="'='"/></xsl:when> 
                    <xsl:otherwise><xsl:value-of select="substring($CODEPAD,((string-length(substring-before($ASCII,substring($CHAR,$CYCLE_CNT*3+2,1)))+1+31) mod 16)*4+1,1)"/></xsl:otherwise> 
                    </xsl:choose> 

                    <xsl:value-of select="'='"/> 
                     
                </xsl:if> 

            </textarea> 
            <xsl:text>解码字符串:</xsl:text> 
            <textarea rows="6" cols="80" style="width:100%"> 

                <xsl:call-template name="base64_decode"> 
                    <xsl:with-param name="number" select="1"/> 
                </xsl:call-template> 

                <xsl:value-of select="substring($ASCII,(((string-length(substring-before($CODEPAD,substring($STR,$CYCLECNT * 4 - 3,1)))+1) mod 256 - 1)*4) + floor(((string-length(substring-before($CODEPAD,substring($STR,$CYCLECNT * 4 - 2,1)))) mod 256) div 16)-31,1)"/> 
                <xsl:choose> 
                <!--第三、四个字符为“=”--> 
                <xsl:when test="substring($STR,$CYCLECNT * 4 - 1,1)='='"></xsl:when> 
                <xsl:otherwise> 
                    <!--第三个字符不为“=”--> 
                    <xsl:value-of select="substring($ASCII,(((string-length(substring-before($CODEPAD,substring($STR,$CYCLECNT * 4 - 2,1)))) mod 16)*16 - 0) + floor(((string-length(substring-before($CODEPAD,substring($STR,$CYCLECNT * 4 - 1,1)))+1) mod 256) div 4) -31,1)"/> 
                    <xsl:choose> 
                    <!--全无“=”--> 
                    <xsl:when test="substring($STR,$CYCLECNT * 4,1)!='='"> 
                        <xsl:value-of select="substring($ASCII,(((string-length(substring-before($CODEPAD,substring($STR,$CYCLECNT * 4 - 1,1)))) mod 4)*64 - 1) + floor(((string-length(substring-before($CODEPAD,substring($STR,$CYCLECNT * 4,1)))+1) mod 255)) - 31,1)"/>
                    </xsl:when> 
                    <!--末字符“=”--> 
                    <xsl:otherwise> 
                    </xsl:otherwise> 
                    </xsl:choose> 
                </xsl:otherwise> 
                </xsl:choose> 

            </textarea> 
        </div> 
    </body> 
</html> 
</xsl:template> 

<!--Encoding&Decoding base64 with XSLT1.0--> 
<!--Author:Qr http://Qr.blogger.org.cn--> 

<xsl:template name="base64_encode"> 
    <xsl:param name="number"/> 
    <xsl:if test="not($number &gt; ($STRLENGTH - $MOD))"> 

        <!--3转4字节第1字符--> 
        <xsl:value-of select="substring($CODEPAD,floor((string-length(substring-before($ASCII,substring($CHAR,$number,1)))+1+31) div 4)+1,1)"/> 

        <!--3转4字节第2字符--> 
        <xsl:value-of select="substring($CODEPAD,((string-length(substring-before($ASCII,substring($CHAR,$number,1)))+1+31) mod 4)*16+floor((string-length(substring-before($ASCII,substring($CHAR,$number+1,1)))+1+31) div 16)+1,1)"/> 

        <!--3转4字节第3字符--> 
        <xsl:value-of select="substring($CODEPAD,((string-length(substring-before($ASCII,substring($CHAR,$number+1,1)))+1+31) mod 16)*4 + floor((string-length(substring-before($ASCII,substring($CHAR,$number+2,1)))+31) div 64)+1,1)"/> 

        <!--3转4字节第4字符--> 
        <xsl:value-of select="substring($CODEPAD,((string-length(substring-before($ASCII,substring($CHAR,$number+2,1)))+1+31) mod 64)+1,1)"/> 

        <!--根据base64的编码规则,每76个字符需要一个换行。根据实际需要取舍--> 
        <!--Firefox未通过。--> 
        <!--number始于1,故只须+2,而不必+3--> 
        <xsl:if test="0=(($number+2) mod 19)">&#x0D;&#x0A;</xsl:if> 

        <xsl:call-template name="base64_encode"> 
            <xsl:with-param name="number" select="$number + 3"/> 
        </xsl:call-template> 

    </xsl:if> 

</xsl:template> 

<!--Encoding&Decoding base64 with XSLT1.0--> 
<!--Author:Qr http://Qr.blogger.org.cn--> 

<xsl:template name="base64_decode"> 

    <xsl:param name="number"/> 
    <xsl:if test="$number &lt; ($STRLEN - 4)"> 
        <!--4转3字节第1字符--> 
        <xsl:value-of select="substring($ASCII,(((string-length(substring-before($CODEPAD,substring($STR,$number,1)))+1) mod 256 - 1)*4) + floor(((string-length(substring-before($CODEPAD,substring($STR,$number+1,1)))) mod 256) div 16)-31,1)"/> 
        <!--4转3字节第2字符--> 
        <xsl:value-of select="substring($ASCII,(((string-length(substring-before($CODEPAD,substring($STR,$number+1,1)))) mod 16)*16 - 0) + floor(((string-length(substring-before($CODEPAD,substring($STR,$number+2,1)))+1) mod 256) div 4)-31,1)"/>
        <!--4转3字节第3字符--> 
        <xsl:value-of select="substring($ASCII,(((string-length(substring-before($CODEPAD,substring($STR,$number+2,1)))) mod 4)*64 - 1) + floor(((string-length(substring-before($CODEPAD,substring($STR,$number+3,1)))+1) mod 255))-31,1)"/> 
        <xsl:call-template name="base64_decode"> 
            <xsl:with-param name="number" select="$number + 4"/> 
        </xsl:call-template> 
    </xsl:if> 
         
</xsl:template> 

<!--Encoding&Decoding base64 with XSLT1.0--> 
<!--Author:Qr http://Qr.blogger.org.cn--> 

</xsl:stylesheet>
 编解码例句这里还是采用Thomas Hobbes's Leviathan文句:

Man is distinguished, not only by his reason, but by this singular passion from other animals, which is a lust of the mind, that by a perseverance of delight in the continued and indefatigable generation of knowledge, exceeds the short vehemence of any carnal pleasure.

编码结果:

TWFuIGlzIGRpc3Rpbmd1aXNoZWQsIG5vdCBvbmx5IGJ5IGhpcyByZWFzb24sIGJ1dCBieSB0aGlz
IHNpbmd1bGFyIHBhc3Npb24gZnJvbSBvdGhlciBhbmltYWxzLCB3aGljaCBpcyBhIGx1c3Qgb2Yg
dGhlIG1pbmQsIHRoYXQgYnkgYSBwZXJzZXZlcmFuY2Ugb2YgZGVsaWdodCBpbiB0aGUgY29udGlu
dWVkIGFuZCBpbmRlZmF0aWdhYmxlIGdlbmVyYXRpb24gb2Yga25vd2xlZGdlLCBleGNlZWRzIHRo
ZSBzaG9ydCB2ZWhlbWVuY2Ugb2YgYW55IGNhcm5hbCBwbGVhc3VyZS4=

以上结果按base64的编码规则76字符换行,解除码时,须将换行相关字符去除再转换,但以上代码没有把这个问题考虑进去,只是将除去换行相关字符的待解码串直接赋值给变量STR。

解码结果:

Man is distinguished, not only by his reason, but by this singular passion from other animals, which is a lust of the mind, that by a perseverance of delight in the continued and indefatigable generation of knowledge, exceeds the short vehemence of any carnal pleasure.

由于映射表中无法将ASCII的控制字符(不可显示字符)加入,因此,待编码字符串只能包含ASCII值小于32和等于127的字符(故TAB和换行等均无法正确编解码),否则,编解码将无法顺利进行,同时也得不到正确的结果。大家如果有兴趣,可以来完善这个功能。

熟悉XSLT&XPath的你一定知道,字符处理并不是XSLT的强项,这项工作本也不该XSLT来做。本文之所以用XSLT来,纯粹学术讨论。

最后,说明一下,编解码过程中,如果把编解码后的字符串组联合起来作为变量再次递归恐怕会影响编解码的速度,所以本例将每组(3转4或4转3)编解码结果直接输出到textarea中,而没有将结果作为变量再次传入命名模板中递归。

 

分享到:
评论

相关推荐

    XSLT1.0 & XPath1.0 快速参考

    ### XSLT1.0与XPath1.0快速参考指南 #### XSLT与XPath简介 XSLT(Extensible Stylesheet Language Transformations)是一种用于转换XML文档的语言,而XPath则是一种在XML文档中查找信息的语言。XSLT 1.0与XPath 1.0...

    XSLT_1.0.rar_Quick

    **XSLT 1.0 快速指南** XSLT(Extensible Stylesheet Language Transformations)1.0是一种强大的语言,用于将XML(Extensible Markup Language)文档转换为其他XML文档、HTML、文本或者任何支持XPath数据模型的...

    xslt-xml2json:基于XSLT1.0的XML到JSON的转换器

    《XSLT1.0实现XML到JSON转换的深度解析》 XML(eXtensible Markup Language)和JSON(JavaScript Object Notation)是两种广泛用于数据交换的格式,各有其优势。XML以其丰富的结构和语义特性在企业级应用中占据...

    XSLT 调用 Java 的类方法

    ### XSLT 调用 Java 的类方法详解 #### 一、背景介绍 XSLT(Extensible Stylesheet Language Transformations)是一种...通过以上步骤,我们可以实现在XSLT中调用Java类方法的功能,从而极大地扩展了XSLT的处理能力。

    'replace' 不是一个有效的 XSLT 或 XPath 函数

    1. XSLT 1.0:不支持 `replace()` 函数,但可以使用模板匹配和`&lt;xsl:value-of&gt;`结合`&lt;xsl:choose&gt;`, `&lt;xsl:when&gt;` 和 `&lt;xsl:otherwise&gt;` 来实现类似的功能,但不够灵活且代码较复杂。 2. XSLT 2.0及以上:引入了 `...

    Learning.XSLT

    Learning XSLT moves smoothly from the simple to complex, illustrating all aspects of XSLT 1.0 through step-by-step examples that you'll practice as you work through the book. Thorough in its coverage ...

    SVG和XSLT实现统计图表源代码

    在"SVG和XSLT实现统计图表源代码"这个项目中,开发者可能利用了SVG的矢量图形能力来创建各种类型的统计图表,如条形图、饼图、折线图等。SVG的优点在于它的图形质量不会因放大而损失,这使得它非常适合用于生成高...

    XSLT Programmer's reference

    XSLT 开发人员指南,书比较老,是针对XSLT 1.0的,学习学习吧。有问题可交流

    XSLT自动代码生成学习笔记

    XSLT有多个版本,最常用的是XSLT 1.0和XSLT 2.0。XSLT 2.0引入了许多新功能,如函数库、类型系统和更复杂的遍历机制,增强了其在代码生成中的应用能力。 2.3 **EXSLT** EXSLT是扩展XSLT的一个开源项目,提供了许多...

    XSL中进行字符串替换

    本文将详细介绍如何通过XSLT实现字符串的替换,并重点探讨两种常用的方法:使用`ms:script`(仅限于Microsoft的XML解析器)以及纯XSL模板。 ### XSL中的字符串替换 #### 使用translate函数 对于简单的字符替换...

    xslt标准

    在企业级系统中,XSLT可用于整合来自不同来源的数据,实现数据的标准化和统一化。 #### 六、结论 XSLT作为一种成熟且功能强大的XML转换语言,对于任何需要处理大量XML数据的开发者来说都是非常有价值的工具。它...

    哈佛大学 xml 课程讲义

    Chapter 4.XPath 1.0(and 2.0) and XSLT 1.0(and 2.0) Chapter 5.XPath 1.0and 2.0) and XSLT 1.0(and 2.0),Continued Chapter 6.Namespaces in XML 1.1(Second Edition) SVG 1.1,and XSL(XSL-FO) 1.1 Chapter 7....

    xslt中调用java

    - Xalan是Apache软件基金会的一个项目,提供了一个实现XSLT 1.0和2.0规范的处理器。Xalan支持创建自定义函数,这些函数可以在XSLT样式表中被调用,实际上它们是用Java编写的。使用`&lt;xsl:extension-element-prefix&gt;`...

    xslt手册

    6. XSLT 1.0与XSLT 2.0/3.0的区别:XSLT 2.0引入了许多新功能,如正则表达式支持、函数库扩展、更多数据类型和更强大的样式表组合能力。XSLT 3.0进一步增强了这些特性,如支持静态类型检查、流式处理API和异步处理。...

    XSLT简单教程- XSLT的实例

    ### XSLT简单教程——XSLT的实例详解 #### 一、XSLT简介与工作...XSLT的强大之处在于它不仅限于简单的文本转换,还可以根据复杂的逻辑和条件来进行数据筛选、排序等多种操作,极大地提升了XML数据的处理能力和灵活性。

    XSLT中文入门 XSLT轻松入门

    总结来说,XSLT作为XML数据转换的语言,其强大之处在于它能够对XML文档进行深度处理,不仅仅是简单的样式调整,而是真正实现了数据的结构性转换。随着XML在互联网和企业信息系统中的广泛应用,XSLT成为了处理XML数据...

    struts2 xslt result 实现

    于是就研究使用Struts2的XSLT result方式来做页面显示。 网上相关的内容非常的少,我也研究了好久才玩转的。一开始总是有一些莫名其妙的问题出现,但最后基本上都是和配置相关的比较多。现在这个例子是整个工程项目...

    jstl-1.0和standard1.0版本

    **JSTL(JavaServer Pages Standard Tag Library)与Standard库1.0版本详解** JSTL,全称为JavaServer Pages Standard Tag Library,是JavaWeb开发中的一个标准标签库,它提供了一系列预定义的标签,用于简化JSP...

    MusicXML 乐谱的转换_XSLT_代码_下载

    所有样式表只需要 XSLT 1.0。一些样式表需要一些 EXSL 函数。它们的名称以 . 为后缀Exsl。 可用转换列表 音乐转变 乐谱部分选择: removeLastPart:删除最后一个分数部分。 removeAllButLastPart:删除除最后一个...

Global site tag (gtag.js) - Google Analytics