XSLT2.0で便利になった機能(17) 数値関係の関数

数値関係の関数について紹介したいと思います.XSLT1.0では数値を表す型が倍精度浮動小数点型のみだったのに対して、XSLT2.0ではXSL Schemaで定義された様々な数値型が使えるように拡張されています.xs:integer,xs:decimal,xs:float,xs:doubleやそれから派生したxs:byte,xs:short,xs:int,xs:longなど.XSLT2.0ではこれらの拡張された数値型が数値関係の関数でも使用できるようになっています.また次のような関数が追加になっています.
 
■ abs()
他のプログラミング言語では馴染み深い関数です.パラメータの絶対値を返します.特殊な場合としてパラメータがNaNの場合はNaNを返します.またパラメータがempty sequenceの場合もempty sequenceを返します.
例を示します.
 
abs(xs:decimal(-3.14))3.14を返します.
abs(number('XXX'))NaN を返します.
abs(())() を返します.
 
avg()
avg()関数は入力sequenceの平均値を返します.入力sequenceは、数値かdurationとされています.ここでは、数値の場合の例を示します.
 
<?xml version="1.0" encoding="UTF-8" ?>
<data>
    <product name="鉛筆">
        <price maker="A" value="100"/>
        <price maker="B" value="110"/>
        <price maker="C" value="150"/>
    </product>
</data>
 
このような入力データで、avg(/data/product[1]/price/@value) は 120 を返します.
 
■ max(), min()
max(), min() は、入力sequenceのなかから、それぞれ最大値、最小値を返します.
avg()の入力データを使うと
 
min(/data/product[1]/price/@value) は 100 を返します.
max(/data/product[1]/price/@value) は 150 を返します.
 
max(),min()は数値だけでなく、lt, gtが使えるもの、例えば文字列も指定できます.この場合第2パラメータにcollationを指定できます.でもあまり文字列の大小比較で最大値・最小値を使うことはないでしょうね.
 
上記の例だとSaxonもAltovaもmin(/data/product[1]/price/@maker)はうまく動いてくれませんでした.スキーマがないのでxs:doubleにキャストしようとしてエラーになってしまうようです.ただし、
 
max(('A','B','X')) はちゃんと 'X' を返します.
 
オープンソースのSaxon-HE 9.2はschema-awareではありません.Saxon-EEを買う必要があります.さすがに買ってないので試せません.Altovaはschema-awareをうたっているようなのですが、XML Schemaを作ってもうまく行きません.@makerをxs:stringに定義しても、やはり数値にxs:doubleにキャストしようとして失敗します.
 
■ round-half-to-even()
一番近い整数に丸めてくれるround()は以前からありましたが、round-half-to-even()は新顔です.この関数は、round-half-to-even(numeric?, xs:integer)の形式で記述します.2番目のパラメータがオプションで、小数点以下の桁数を指定します.
 
round-half-to-even(3.1425,3) は 3.142 を返します.
round-half-to-even(3.1415,3) は 3.142 を返します.
round-half-to-even(3.1414,3) は 3.141 を返します
round-half-to-even(0.9e0 div 9, 5) は 0.1 を返します.
 
例を見ておわかりでしょうか?1番目と2番目の例にあるようにhalf-to-evenというところがミソですね.単純に0.5を1にしていない訳です.サンプルが多ければ平均をとったときにこちらの方がより正確な値がでるでしょう.