XSL实现十六进制RGB值转换为十进制颜色值 

2008/8/1 22:20:55


阅读全文(6506) | 回复(1) | 编辑 | 精华

XSL实现十六进制RGB值转换为十进制颜色值-----------------------------------Qr原创,Qr'blog http://Qr.blogger.org.cn2008/08/01----------------------------------- 前些日子,论坛http://bbs.xml.org.cn上有个贴子问关于十六进制RGB值转换为十进制颜色值。我给的思路比较简单,当然只是半成品: <xsl:template match="//color"><xsl:variable name="n1" select="number(substring(@val,1,1))"/><xsl:variable name="n2" select="number(substring(@val,2,1))"/><xsl:variable name="n3" select="number(substring(@val,3,1))"/><xsl:variable name="n4" select="number(substring(@val,4,1))"/><xsl:variable name="n5" select="number(substring(@val,5,1))"/><xsl:variable name="n6" select="number(substring(@val,6,1))"/><color>        RGB(                <xsl:value-of select="$n1*16+$n2"/>,                <xsl:value-of select="$n3*16+$n4"/>,                <xsl:value-of select="$n5*16+$n6"/>        )</color></xsl:template> ---------------------------------------------------Qr'blog http://blogger.org.cn/blog/blog.asp?name=Qr--------------------------------------------------- 因为涉及到十六进制到十进制的转换,所以,仅以上简码并不能帮上什么大忙。实际上,字符A-F与10-15对应的转换关系才是问题的核心。 首先,我们先来了解十六进制转换到十进制的对应关系: [十六进制]    0    1    2    3    4    5    6    7    8    9    A    B    C    D    E    F[十 进 制]    0    1    2    3    4    5    6    7    8    9    10   11   12   13   14   15 假设有这么一个十六进制数2A5F,要转换成十进制数,则2A5F(H) = 2*16^3 + A*16^2 + 5*16^1 + F*16^0        = 2*16^3 + 10*16^2 + 5*16^1 + 15*16^0        = 8192 + 2560 + 80 + 15        = 10847(D) 说明: 16^n 表示16的n次方。 ---------------------------------------------------Qr'blog http://blogger.org.cn/blog/blog.asp?name=Qr--------------------------------------------------- 那么,用XSLT如何实现色值的十六进制到十进制转换呢?十六进制的色值(#RRGGBB)是由长度为6位十六进制数两两组合而成,每两位数表示一个色素。如果转换成十进制的表示方法,则需要将6位十六进制数字两两一组转换。先看一个示例:#FF0000 = (FF),(00),(00)        = (15*16^1 + 15*16^0),(0),(0)        = (255),(0),(0)        = RGB(255,0,0) 接着,我们XSLT是如何实现上面这个关系的转换的: <?xml version="1.0"?><xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"><xsl:output method="xml" version="1.0" indent="yes" /> <!--xsl:template match="//color"><xsl:variable name="n1" select="number(substring(@val,1,1))"/><xsl:variable name="n2" select="number(substring(@val,2,1))"/><xsl:variable name="n3" select="number(substring(@val,3,1))"/><xsl:variable name="n4" select="number(substring(@val,4,1))"/><xsl:variable name="n5" select="number(substring(@val,5,1))"/><xsl:variable name="n6" select="number(substring(@val,6,1))"/><color>            RGB(                <xsl:value-of select="$n1*16+$n2"/>,                <xsl:value-of select="$n3*16+$n4"/>,                <xsl:value-of select="$n5*16+$n6"/>        )</color></xsl:template--> <xsl:template match="/"><root>            <xsl:apply-templates select="//color"/></root></xsl:template> <xsl:template match="color"><color>            RGB(                <xsl:call-template name="RGB">                        <xsl:with-param name="pos" select="1"/>                </xsl:call-template>        )</color><br/></xsl:template> <xsl:template name="RGB">        <xsl:param name="pos"/>        <xsl:if test="$pos &lt; 6">                <xsl:variable name="tmp1" select="substring(@val,$pos,1)"/>                <xsl:variable name="tmp2" select="substring(@val,$pos+1,1)"/>                <xsl:variable name="CL">                        <xsl:choose>                                <xsl:when test="$tmp1='A'">10</xsl:when>                                <xsl:when test="$tmp1='B'">11</xsl:when>                                <xsl:when test="$tmp1='C'">12</xsl:when>                                <xsl:when test="$tmp1='D'">13</xsl:when>                                <xsl:when test="$tmp1='E'">14</xsl:when>                                <xsl:when test="$tmp1='F'">15</xsl:when>                                <xsl:otherwise><xsl:value-of select="$tmp1"/></xsl:otherwise>                        </xsl:choose>                </xsl:variable>                <xsl:variable name="CR">                        <xsl:choose>                                <xsl:when test="$tmp2='A'">10</xsl:when>                                <xsl:when test="$tmp2='B'">11</xsl:when>                                <xsl:when test="$tmp2='C'">12</xsl:when>                                <xsl:when test="$tmp2='D'">13</xsl:when>                                <xsl:when test="$tmp2='E'">14</xsl:when>                                <xsl:when test="$tmp2='F'">15</xsl:when>                                <xsl:otherwise><xsl:value-of select="$tmp2"/></xsl:otherwise>                        </xsl:choose>                </xsl:variable>                <xsl:value-of select="$CL*16+$CR"/>                <xsl:if test="$pos &lt; 5">,</xsl:if>                <xsl:call-template name="RGB">                        <xsl:with-param name="pos" select="$pos + 2"/>                </xsl:call-template>        </xsl:if></xsl:template></xsl:stylesheet> 下面是对以上代码的解释:转换起始于<xsl:call-template>对命名模板RGB的调用,整个代码并没有定义与十六进制色值字符串相关的变量,只定义了一个与字符串截取位置变量pos,这是十六进制色值字符串两两分组的关键。第1次调用命名模板RGB的时候,pos=1,变量tmp1和tmp2分别取得的是十六进制色值字符串的第1、2个字符,然后分别判断并将其对应的数值赋给变量CL和CR,将两变量代入公式$CL*16+$CR即可计算出RR对应的十进制值;接着,第2次调用命名模板RGB(此次调用是在命名模板RGB内部调用,也就是我们常说的递归),由于<xsl:with-param name="pos" select="$pos + 2"/>使得pos=3,并取得GG的对应十进制值;然后第3次调用(还是递归)命名模板RGB,此时pos=5,BB的对应十进制值也就可以得到了。命名模板RGB三次被调用,递归结束,我们想要的结果也就出来了。很口语化吧,希望有助于你对代码的理解。 ---------------------------------------------------Qr'blog http://blogger.org.cn/blog/blog.asp?name=Qr--------------------------------------------------- 纵观全部XSL代码,变量CL和CR的获取显得不是很专业,记得好象在IBM的网站上针对<xsl:choose>有这么一句话,“这是初学者才会用的方法”,下面我们对代码进行重构: 让我们再回过头去看看十六进制转换到十进制的对应关系,如果我们把16个十六进制数字按顺序连成一个字符串,每个字符所在字符串的序号是不是就是对应的十进制数字?!说到这不知道大家明白了没有,反正我已经知道如何去实现代码的重构了。 首先,先定义一个变量,该变量的值就是16个十六进制数字按顺序连成的字符串,如下: <xsl:variable name="char" select="'0123456789ABCDEF'"/> 注意哦,一定要将这个变量定义为全局的,否则代码出错可别怪我没贴出完整代码。 接下来的关键语句:每个字符所在字符串的序号是不是就是对应的十进制数字?!我们现在就把这句话用XSL来描述:         <xsl:variable name="CL" select="string-length(substring-before($char,substring(@val,$pos,1)))"/>        <xsl:variable name="CR" select="string-length(substring-before($char,substring(@val,$pos+1,1)))"/> 好了,不管你读懂前面的关键语句与否,反正我的代码已经重构完成,代码比原来锐减了21行。 ---------------------------------------------------Qr'blog http://blogger.org.cn/blog/blog.asp?name=Qr--------------------------------------------------- 如果你还没理解前面的代码是如何工作的,或者说是你根本就不知道命名模板的递归作用,那干脆不要去深究了。没错,下面的代码根本没用到命名模板,更不用说XSL中晦涩难懂的模板递归了:         RGB(                <xsl:value-of select="string-length(substring-before($char,substring(@val,1,1)))*16+string-length(substring-before($char,substring(@val,2,1)))"/>,                <xsl:value-of select="string-length(substring-before($char,substring(@val,3,1)))*16+string-length(substring-before($char,substring(@val,4,1)))"/>,                <xsl:value-of select="string-length(substring-before($char,substring(@val,5,1)))*16+string-length(substring-before($char,substring(@val,6,1)))"/>        ) 好了,关于十六进制RGB值转换为十进制颜色值就讨论到这里。提醒和总结一下,三种方法的中心思想归根结底都是HEX2DEC[COLOR]:mn(HEX)=m*16^1+n*16^0=m*16+n(DEC)第三种方法和第二种方法其实上没有本质的区别,只是前者使用模板递归,后者没有使用模板递归。 最后,给出测试用的XML文档<?xml version="1.0"?> <root>        <color val="FF0000"/>        <color val="00FF00"/>        <color val="0000FF"/>        <color val="123456"/></root> ---------------------------------------------------Qr'blog http://blogger.org.cn/blog/blog.asp?name=Qr---------------------------------------------------

Qr

Posted by Qr on 2008/8/1 22:20:55

回复:XSL实现十六进制RGB值转换为十进制颜色值

2008/8/2 8:44:01


个人主页 | 引用回复 | 主人回复 | 返回 | 编辑 | 删除

收藏 留作参考,谢谢!! 以下为blog主人的回复: 随便写写

hjx_221

Posted by hjx_221 on 2008/8/2 8:44:01

» 1 »

发表评论:
昵称:
密码:
主页:
标题:
验证码:  (不区分大小写,请仔细填写,输错需重写评论内容!)
站点首页 | 联系我们 | 博客注册 | 博客登陆

Sponsored By W3CHINA
W3CHINA Blog 0.8 Processed in 2.227 second(s), page refreshed 144749463 times.
《全国人大常委会关于维护互联网安全的决定》  《计算机信息网络国际联网安全保护管理办法》
苏ICP备05006046号