XSLT2.0で便利になった機能(11) 文字列比較

XSLT1.0(XPath 1.0)では、文字列の大小比較はできませんでした.今考えると大変不便な話だったのですが、よくなんの疑問もなく使ったものです.XSLT2.0ではバッチリできるようになっています.
 
復習してみますとXSLT1.0では文字列の比較といえば、一致判定の <xsl:if test="$x = 'abc'"> は、$x と 'abc'を比較し、一致するか否かでtrue()かfalse()を返してくれます.ところが大小判定をやろうとして <xsl:if test="$x &gt; 'abc'"> とか、<xsl:if test="$x &lt; 'abc'"> とやると、この場合 $x の内容にかかわらず必ずfalse() が返ります.
 
これは、XPath1.0では、"<"、">"、"<="、">="のオペレータについては、必ず両辺が数値比較されてしまうからです.上記の式では、number('abc')は数値に変換できないのでNaNになります.NaNとの数値比較は相手が何であろうと常にfalse()になってしまいます.
 
XPath 2.0では、<xsl:if test="$x gt 'abc'">とか、<xsl:if test="$x lt 'abc'">では、「デフォルトのコレーション」にもとづいて比較が行われtrue()/false()が返ってくれます.例えば
 
boolean('bcd' gt 'abc')はtrue()です.
boolean('bcd' lt 'abc')はfalse()です.
 
ところで、XSLT2.0で使える文字列の関数の中で、文字列の比較のcompare()というのがあります.最初、何故このような関数があるのか疑問でした.ge、gt、le、lt、eqで十分ではないのかと.しかし、パラメータを見て理解できました.compare()は、第1パラメータstring-1がxs:string、第2パラメータstring-2がxs:string、第3パラメータがオプションでコレーションを示すxs:stringのURIになっています.このコレーションがミソです.compare()は
 
string-1 lt string-2のとき-1を、string-1 gt string-2のとき+1を、string-1 eq string-2のとき0を返してくれます.
 
ふだんはあまり気にならないのですが、ソートを行うときに「コレーション」(文字の比較順序)は重要になってきます.文字の大小関係が言語により異なるからです.SaxonではコレーションのURIの指定方法として
 
 
をサポートしています.例えば、デフォルトのコレーションを使うeqでは
 
boolean('づ' eq 'つ&#x3099;') はfalse()ですが、
 
compare('づ','つ&#x3099;','http://saxon.sf.net/collation?lang=ja;';) は0を返します.
 
すなわち日本語のコレーションでは両者は等しいと判定してくれます.(&#x3099;は「結合する濁点」です)
 
コレーションは文字の比較のcompare()だけでなく、<xsl:sort> にもパラメータとして登場します.これを使えば、各国語に即した並べ替えもできますね.