XSLT2.0で便利になった機能(13) Unicodeの正規化

ふだんはあまり気にすることがないのですが、例えば同じ文章をXML化するとき、必ずしも同じ結果が得られる保障はありません.まずはエンコーディングShift_JISUTF-16から、UTF-8など、決まりを作っておかねば、いろいろなXML文書が作れてしまいます.またタグにしても、<br/>と<br></br>は同じ意味ですが、データの表現方法としては違ってしまいます.W3Cではこのような問題に対処するために、
 
 
という勧告を作成して統一化を図っています.例えばエンコーディングUTF-8にすること、XML宣言は省略する.空タグではなく<br></br>のような開始タグ、終了タグのペアーを使用することなど.
 
しかし、この勧告の中では文字の正規化に関しては、勧告外の扱いとしています.この事情に関しては「4.2 No Character Model Normalization」に詳しいので御覧ください.
 
さてここで文字の正規化とは、たとえば日本語だったら、"ば" を U+3070 で表すのか、"は" + "゛" (U+306FとU+309B) で表すのかということ、累乗数を意味と等価の上付きで表すのか、それとも単に文字の並びとして通常の数字で表すのかなどに関する仕様と考えれば良いでしょう.
 
正規化の形式は、NFC、NFD、NFKC、NFKDなどといろいろあり、
 
 
で規定されています.(ややこしくなってきました...このあたりはWikipediaを見たほうがわかりやすいです. )
 
 
XSLT2.0のnormalize-unicode()関数は、文字列と正規化の形式を指定して、結果を得ることができます.例えば、normalize-unicode()のデフォルトの正規化の形式はNFCで、例えば先ほどの "は" + "゛"の文字列を "ば" に統合してくれます.
 
試してみると、
 
boolean(normalize-unicode('は&#x3099;') eq 'ば') =true()
boolean(normalize-unicode('は&#x3099;','NFC') eq 'ば') =true()
 
になります.&#x3099;は「結合する濁点」です.
ちなみに
 
boolean(normalize-unicode('ば','NFD') eq 'は&#x3099;')=true()
boolean(normalize-unicode('2&#x00B3;','NFKD') eq '23')=true()
 
になります.&#x00B3;は2乗の上付き文字です.
 
XSLT1.0ではこの分野には手段がありませんでした.パーサー任せです.文字列の正規化関数が取り入れられることにより、さまざまな正規化形式の文字列でも、対処できるようになるでしょう.また正規化形式は、<xsl:output>のシリアライズのパラメータにもあります.入り口のパーサーがサポートしていなくとも、XSLTで正規化を実現して出力することも可能になっています.
 
# 文字コード表、以下から御参照ください.
Latin-1 Supplement http://www.unicode.org/charts/PDF/U0080.pdf
Hiragana http://www.unicode.org/charts/PDF/U3040.pdf