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 < 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 < 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---------------------------------------------------
Posted by Qr on 2008/8/1 22:20:55
回复:XSL实现十六进制RGB值转换为十进制颜色值
2008/8/2 8:44:01
个人主页 | 引用回复 | 主人回复 | 返回 | 编辑 | 删除
收藏 留作参考,谢谢!! 以下为blog主人的回复: 随便写写
Posted by hjx_221 on 2008/8/2 8:44:01
发表评论: |
|