数学运算和XSLT
by Bob DuCharme 编译:王顺 XSLT对XPath的数学性能的完全支持使人们可以做所有基本类型的算法或者更多!让我们看一下一个通过使用下面文件的值来示范这些性能的样式表:
4
3.2
11
样式表的A到N每行均进行着(或者试图进行)一个不同的计算。这些计算使用上面文件中给出的数字和其他一些或者是样式表中固定的代码或者是从函数中返回的数值得到的值。
A. 4 + 3.2 =
B. 3.2 - 4 =
C. 4 * 3.2 =
D. 11/3.2 =
E. 4 + 3.2 * 11 =
F. (4 + 3.2) * 11 =
G. 11 mod 4 =
H. 4 + 3.2 + 11 =
I. floor(3.2) =
J. ceiling(3.2) =
K. round(3.2) =
L. 11 + count(*) =
M. 3.2 + string-length("3.2") =
N. 11 + "hello" =
在我们讨论每一行具体做什么之前,让我们先看一下将样式表应用到数字文件中的结果。
A. 4 + 3.2 = 7.2
B. 3.2 - 4 = -0.8
C. 4 * 3.2 = 12.8
D. 11/3.2 = 3.4375
E. 4 + 3.2 * 11 = 39.2
F. (4 + 3.2) * 11 = 79.2
G. 11 mod 4 = 3
H. 4 + 3.2 + 11 = 18.2
I. floor(3.2) = 3
J. ceiling(3.2) = 4
K. round(3.2) = 3
L. 11 + count(*) = 14
M. 3.2 + string-length("3.2") =
6.2
N. 11 + "hello" = NaN
这个样式表对源树中的numbers元素具有一个单一的模板规则。这个模板有一系列的 xsl:value-of 指令,它们用来选择属性使用numbers元素的x、y和z子元素的数值去进行各种不同的数学计算。类似的这些数学公式可以使用XPath的全部功能来表示哪些元素或属性具有他们需要的数字;但是,这个样式表更加注重于说明与使用奇特的XPath表达式从一个文件的余部找回元素和属性相比它可用的数学运算的范围。
模板的行A将x的值(4)加到y的值(3.2)上并将他们的和7.2放到结果树中。这是非常简单的、直观的,并显示了并不需要限制在样式表数学中为整数。
行B从3.2中减掉了4得到结果为-0.8。负数并没有给XSLT处理器带来任何的困难。
警告: 对某些XSLT处理器,十进制数字的使用可能引入一个微小的误差。例如,这个例子中的"3.2 - 4"在有些处理器中得到的结果为"-.7999999999999998"。 .0000000000000002的误差很小,但从根本上说明数学并不是XSLT的强项。
行C用4乘3.2,使用星号作为乘法运算符,其结果为12.8。
行D用3.2除z元素(11),说明了一个XSLT处理器执行浮点除法运算的能力。尽管大多数的编程语言在传统上使 用斜线字符(/)表示除法运算符,但是Xpath已经将斜线字符用来分段Xpath位置路径(例如, wine/vintage 表示了vintage 元素为 wine 元素的子元素)。因此,Xpath和XSLT用字符"div" 表示除法。
行E和F显示了圆括号与在正常的数学符号中具有同样的操作优先权:不使用圆括号,先乘后加,所以4 + 3.2 * 11 = 4 + 35.2。对"4+3.2"使用圆括号后,先进行加法运算,所以(4 + 3.2) * 11 = 7.2 * 11。
行G示范了mod 运算符,它得到了两数相除的余数。例中为11 mod 4 结果为3,因为11除以4得2余3。这个运算符主要用来检查一个数是否能被另一个数均分;即检查大数mod小数是否等于0。
行H示范了sum() 函数。用节点列表作为参数,它加和了列表中所有节点的数值。在本例中星号的意思是"范围节点内的所有子节点"--即numbers元素的x, y和z 子元素。
行I和J示范了floor() 和ceiling() 函数。如果它们传入的参数为整数,它们即返回该整数。如果传入floor() 一个非整数,将返回一个小于该数的最大整数。本例中为floor(3.2)结果为3。ceiling函数将返回大于该数(非整数)的最小整数;例中 ceiling(3.2)结果为4。
行K的round()函数把一个非整数舍入为一个最接近的整数。 当传入参数为3.2时,返回值为3;传入3.5或3.6时,它的返回值将变为4。
行L具体表现了另一个Xpath函数:count(),它将返回作为参数传给它的节点集的个数。Xpath提供几个函数,当数学上不明确时,返回数值并可以用于各种计算:count(), last(), position()和string-length()。行M示范了string-length(),它将返回该字符串的长度。
行N显示了当试图对一些不是数字的东西执行数学运算时得到的结果:当11加上字符串"hello"时,得到的结果为字符串"NaN",即"Not a Number."的缩写。当你把一个数字作为一个元素的内容或者是属性值,然后用它来进行计算,将不能保证它真正的是一个数字,所以XSLT明确定义了不能实行的情况的状态,使之更加容易的检测和处理你的代码。
XSLT是用来处理文本,而不是数字;但是你可以用作为XSLT一部分提供的数学运算符来构建和执行更多复杂的计算。例如,下面的样式表,它可以接受任何文件作为输入,计算 pi的值。其结果的精度依赖于迭代变量的值。
>
1
0
循环通过利用一个递归的命名模板(named template)来实现。根据迭代设置显示,该样式表得到的结果为:
3.1415676535897985
经过多次迭代,结果仅仅精确到小数点后的第四位数字。当然如果你想认真地计算PI的值,有更多合适的编程语言。但是知道了在必要的时候可以使用XSLT来做一些相对复杂的数学运算还是很不错的。