こんなことを書くと「あったりまえじゃん!」と言われそうですが、それでもXSLT 1.0のスタイルシートを見ていると意外とそのまま動いてしまっている例があります.それはXPath式でのロケーションステップに対する述語(predicate)の"[1]"という記述です.
例えば入力のXMLが
<doc>
<chapter>
<para no="1">para-1</para>
<para no="2">para-2</para>
<para no="3">para-3</para>
<para no="4">para-4</para>
</chapter>
<chapter>
<para no="5">para-5</para>
<para no="6">para-6</para>
<para no="7">para-7</para>
<para no="8">para-8</para>
</chapter>
</doc>
という単純なものであり、XSLT 1.0で"1番目のpara要素の中身を出力しよう"と次のように書いたとします.
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0">
<xsl:template match="/">
<xsl:variable name="para1" select="//para[1]"/>
<xsl:message>//para[1]=<xsl:value-of select="string($para1)"/></xsl:message>
</xsl:template>
</xsl:stylesheet>
結果は、oXygenでやると、
//para[1]=para-1
となります.なんの問題もありません.でもここで、xsl:stylesheetのversion="2.0"に書き換えて実行すると、
XPTY0004: A sequence of more than one item is not allowed as the first argument of string() (<para/>, <para/>)
のエラーになってしまいます.何か変です.デバッグのために、
<xsl:message select="'//para[1]=',//para[1]"></xsl:message>
と書いてやると、
//para[1]=<para no="1">para-1</para><para no="5">para-5</para>
と出てきます.アレッ!?話が違うようです.//para[1]は<para no="1">para-1</para>だけでなく<para no="5">para-5</para>も選択しています.そうなのです.ここで知らなければならないことは次のようなことです.
1. 述語(predicate)に"[1]"と書くと、それはコンテキストポジション(context position)の意味になります."[1]"は実は"[position() = 1]"と等価です.ここでposition()は評価されている要素の順番を返します.つまり対象はpara要素ですから、position()は、そのpara要素の親に対して何番目の子かということです.すべてのpara要素のうちの1番目ということにはならないのです.
2. もし文書中のすべてのpara要素のドキュメントオーダーで1番目ということだったら、<xsl:message select="'(//para)[1]=',(//para)[1]"></xsl:message>と書かねばなりません.こうすれば、(//para)[1]=<para no="1">para-1</para>と表示されます.評価されるものは文書中のすべてのparaのシーケンスだからです.その中での1番目を選択することになります.
3. XSLT 1.0では、string関数のパラメータが複数ノードの場合、最初のノードが選択されてその文字列値が返されます.XSLT 2.0ではこのようにはならず、string関数のパラメータがノードの場合、その個数は一個でなければ上記のようにエラーとなります.これはXSLT 2.0プロセッサを使っていても、XSLTスタイルシートのversion="1.0"か"2.0"かで異なった動作となります.
という訳でたかだか"[1]"であっても結構いろいろ知らねばならないことはあったのでした.参考になれば幸いです.