先だって
<?xml version="1.0" encoding="UTF-8" ?>
<div>
<span>りんご</span>
<span>みかん</span>
<span>バナナ</span>
</div>
<div>
<span>りんご</span>
<span>みかん</span>
<span>バナナ</span>
</div>
と書いて
<xsl:variable name="div_seq" as="node()*">
<xsl:sequence select="/div/span[1]"/>
<xsl:sequence select="/div/span[2]"/>
<xsl:sequence select="/div/span[3]"/>
</xsl:variable>
<xsl:sequence select="/div/span[1]"/>
<xsl:sequence select="/div/span[2]"/>
<xsl:sequence select="/div/span[3]"/>
</xsl:variable>
と書くと、node()*には元のツリーのノードが保持されると書きました.XSLTではgenerate-id()というノードを識別するidを返す関数があるので、これを使って試してみます.
<xsl:message select="'/div/span[1]=',generate-id(/div/span[1]),' contents=',/div/span[1]"/>
<xsl:message select="'/div/span[2]=',generate-id(/div/span[2]),' contents=',/div/span[2]"/>
<xsl:message select="'/div/span[3]=',generate-id(/div/span[3]),' contents=',/div/span[3]"/>
<xsl:message select="'/div/span[2]=',generate-id(/div/span[2]),' contents=',/div/span[2]"/>
<xsl:message select="'/div/span[3]=',generate-id(/div/span[3]),' contents=',/div/span[3]"/>
<xsl:message select="'$div_seq[1]=',generate-id($div_seq[1]),' contents=',$div_seq[1]"/>
<xsl:message select="'$div_seq[2]=',generate-id($div_seq[2]),' contents=',$div_seq[2]"/>
<xsl:message select="'$div_seq[3]=',generate-id($div_seq[3]),' contents=',$div_seq[3]"/>
<xsl:message select="'$div_seq[2]=',generate-id($div_seq[2]),' contents=',$div_seq[2]"/>
<xsl:message select="'$div_seq[3]=',generate-id($div_seq[3]),' contents=',$div_seq[3]"/>
とやってみると、出力は
/div/span[1]= d2e3 contents=<span>りんご</span>
/div/span[2]= d2e6 contents=<span>みかん</span>
/div/span[3]= d2e9 contents=<span>バナナ</span>
$div_seq[1]= d2e3 contents=<span>りんご</span>
$div_seq[2]= d2e6 contents=<span>みかん</span>
$div_seq[3]= d2e9 contents=<span>バナナ</span>
/div/span[2]= d2e6 contents=<span>みかん</span>
/div/span[3]= d2e9 contents=<span>バナナ</span>
$div_seq[1]= d2e3 contents=<span>りんご</span>
$div_seq[2]= d2e6 contents=<span>みかん</span>
$div_seq[3]= d2e9 contents=<span>バナナ</span>
となります.確かにnode()*はソースのツリーを指しています.
では、
<xsl:variable name="div_ns" as="document-node()">
<xsl:document>
<xsl:sequence select="/div/span[1]"/>
<xsl:sequence select="/div/span[2]"/>
<xsl:sequence select="/div/span[3]"/>
</xsl:document>
</xsl:variable>
<xsl:document>
<xsl:sequence select="/div/span[1]"/>
<xsl:sequence select="/div/span[2]"/>
<xsl:sequence select="/div/span[3]"/>
</xsl:document>
</xsl:variable>
とやるとどうなるのでしょうか?
この場合
<xsl:message select="'$div_ns/*[1]=',generate-id($div_ns/*[1]),' contents=',$div_ns/*[1]"/>
<xsl:message select="'$div_ns/*[2]=',generate-id($div_ns/*[2]),' contents=',$div_ns/*[2]"/>
<xsl:message select="'$div_ns/*[3]=',generate-id($div_ns/*[3]),' contents=',$div_ns/*[3]"/>
<xsl:message select="'$div_ns/*[2]=',generate-id($div_ns/*[2]),' contents=',$div_ns/*[2]"/>
<xsl:message select="'$div_ns/*[3]=',generate-id($div_ns/*[3]),' contents=',$div_ns/*[3]"/>
とやると、
$div_ns/*[1]= d3e1 contents=<span>りんご</span>
$div_ns/*[2]= d3e3 contents=<span>みかん</span>
$div_ns/*[3]= d3e5 contents=<span>バナナ</span>
$div_ns/*[2]= d3e3 contents=<span>みかん</span>
$div_ns/*[3]= d3e5 contents=<span>バナナ</span>
となります.
つまり<xsl:document>~</xsl:document>の中ではノードがコピーされて新しくツリーが構築されます.元のツリーの兄弟関係はなくなり、新たなノードで再構築されます.ここはすごく大事なところです.こうなってくれないと、テンプレート間でテンポラリーツリーを更新しながら受け渡すような再帰的なプログラムはうまく動いてくれません.
実際
<xsl:variable name="div_ns" as="document-node()">
<xsl:document>
<xsl:sequence select="/div/span[1]"/>
<xsl:sequence select="/div/span[2]"/>
<xsl:sequence select="/div/span[3]"/>
<xsl:sequence select="/div/span[1]"/>
</xsl:document>
</xsl:variable>
<xsl:document>
<xsl:sequence select="/div/span[1]"/>
<xsl:sequence select="/div/span[2]"/>
<xsl:sequence select="/div/span[3]"/>
<xsl:sequence select="/div/span[1]"/>
</xsl:document>
</xsl:variable>
として、二回ノードをコピーすると
<xsl:message select="'$div_ns/*[3]=',generate-id($div_ns/*[3]),' contents=',$div_ns/*[3]"/>
<xsl:message select="'$div_ns/*[4]=',generate-id($div_ns/*[4]),' contents=',$div_ns/*[4]"/>
<xsl:message select="'$div_ns/*[3]/following-sibling::*[1]=',$div_ns/*[3]/following-sibling::*[1]"/>
<xsl:message select="'generate-id($div_ns/*[3]/following-sibling::*[1])=',generate-id($div_ns/*[3]/following-sibling::*[1])"/>
<xsl:message select="'$div_ns/*[4]=',generate-id($div_ns/*[4]),' contents=',$div_ns/*[4]"/>
<xsl:message select="'$div_ns/*[3]/following-sibling::*[1]=',$div_ns/*[3]/following-sibling::*[1]"/>
<xsl:message select="'generate-id($div_ns/*[3]/following-sibling::*[1])=',generate-id($div_ns/*[3]/following-sibling::*[1])"/>
は
$div_ns/*[3]= d3e5 contents=<span>バナナ</span>
$div_ns/*[4]= d3e7 contents=<span>りんご</span>
$div_ns/*[3]/following-sibling::*[1]=<span>りんご</span>
generate-id($div_ns/*[3]/following-sibling::*[1])= d3e7
$div_ns/*[4]= d3e7 contents=<span>りんご</span>
$div_ns/*[3]/following-sibling::*[1]=<span>りんご</span>
generate-id($div_ns/*[3]/following-sibling::*[1])= d3e7
と出力されます.ツリーが再構築されているのがわかります.このような点もnode()*とdocument-node()は決定的に違います.
先ほど言及したテンプレート間でテンポラリーツリーを更新しながら受け渡すような再帰的なプログラムでは、やはりdocument-node()が便利です.node()*を使ってできないことはないでしょうが、やはり向いていないでしょう.