昨天水木XML版有网友问了这样的问题:
<node count="0x123"/> 如下的xpath不工作:
//node[@count>100]
XPath标准中数学函数暂时都只能处理十进制数字,那样就得把XML中的十六进制转成十进制,既然涉及到XML文档内容的转换,马上想到XSLT。网上搜到开源项目XSLT Standard Library(http://xsltsl.sourceforge.net/ ,这个项目很久没更新了,但代码写得很好。),其中的数学函数模块实现了十六进制转十进制的功能,模仿这个实现,编写了下面的代码。
测试XSLT模板用的xsltproc: xsltproc hex2dec.xsl test.xml
===========================================
<? xml version ="1.0" ?>
<! --
Introduction: 十六进制数字转十进制,参考Xslt Standard Library实现.
Author: thinkhy@newsmth.net
Date: 2009年 10月 31日 星期六 14:55:44 CST
-- >
< xsl : stylesheet version ="1.0"
xmlns : xsl ="http://www.w3.org/1999/XSL/Transform "
>
<! --Hex/Dec 数字映射-- >
< xsl : template name ='hex-digit-map' >
< xsl : param name ='digit' select ='0' />
< xsl : choose >
< xsl : when test ='$digit & lt ; = 9' >
< xsl : value-of select ='$digit' />
</ xsl : when >
< xsl : when test ='$digit = "a" or $digit = "A"' > 10</ xsl : when >
< xsl : when test ='$digit = "b" or $digit = "B"' > 11</ xsl : when >
< xsl : when test ='$digit = "c" or $digit = "C"' > 12</ xsl : when >
< xsl : when test ='$digit = "d" or $digit = "D"' > 13</ xsl : when >
< xsl : when test ='$digit = "e" or $digit = "E"' > 14</ xsl : when >
< xsl : when test ='$digit = "f" or $digit = "F"' > 15</ xsl : when >
</ xsl : choose >
</ xsl : template >
<! --十六进制转十进制-- >
< xsl : template name ="hex2decimal" >
< xsl : param name ="value" />
< xsl : choose >
< xsl : when test ='$value = ""' />
< xsl : when test ='string-length($value) = 1' >
< xsl : call-template name ='hex-digit-map' >
< xsl : with-param name ='digit' select ='$value' />
</ xsl : call-template >
</ xsl : when >
< xsl : otherwise >
< xsl : variable name ='first-digit' >
< xsl : call-template name ='hex-digit-map' >
< xsl : with-param name ='digit' select ='substring($value, 1, 1)' />
</ xsl : call-template >
</ xsl : variable >
< xsl : variable name ='remainder' >
< xsl : call-template name ='hex2decimal' > <! --递归调用-- >
< xsl : with-param name ='value' select ='substring($value, 2)' />
</ xsl : call-template >
</ xsl : variable >
< xsl : value-of select ='$first-digit * 16 + $remainder' />
</ xsl : otherwise >
</ xsl : choose >
</ xsl : template >
<! --原样输出所有结点-- >
< xsl : template match ="node()" >
< xsl : copy >
< xsl : apply-templates select ="@*|node()" />
</ xsl : copy >
</ xsl : template >
<! --转换count属性中十六进制-- >
< xsl : template match ="@count" >
< xsl : attribute name ="count" >
<! --调用转换模板-- >
< xsl : call-template name ="hex2decimal" >
< xsl : with-param name ='value' select ='substring(.,3)' />
</ xsl : call-template >
</ xsl : attribute >
</ xsl : template >
<! -- <xsl:template match="text()"/>-- >
</ xsl : stylesheet >