検索範囲(軸)、リミット、Next-sibling範囲
情報抽出(extraction)の検索範囲とは、基本的にノード集合(空集合のときもある)だが、次の構造を持つ。
- 侵入的順序構造:パターンマッチングの失敗時と、侵入的パターンによるマッチングの成功時に「次」を決めるために使用する順序。線形順序である。
- 非侵入的順序構造:非侵入的パターンによるマッチングの成功時に「次」を決めるために使用する順序。部分順序でよい。
侵入的順序と非侵入的順序が異なるのは、Descendant範囲(軸)だけで、他のタイプの検索範囲では侵入的順序と非侵入的順序は一致する。
検索範囲に含まれるノードの個数(集合の基数)をサイズと呼ぶ(XPathの用語)。パターンマッチングが成功できる最大数をリミットと呼ぶ。
今までは、リミット=サイズ という前提だったので、特にリミットを意識する必要はなかった。しかし、Next-sibling範囲ではリミットとサイズは異なることがある。リミットは常に1(1回を越えて成功はできない、高々1回の成功まで)であるが、Next-sibling範囲のサイズは1を超えることがある。
このような現象が起きるのは、(text), (pi-or-comment), (node) というCSSにはないセレクターを導入したためである。これらの特別なセレクターと'+'コンビネータの折り合いを付けるためには、リミットとサイズが違うことを認める必要がある。
次のパターンを考える。
<div#this> + <p>$:text</> </>
HTMLとして:
<div id="this">...</div> <p>...</p>
Next-sibling範囲を、DOMツリー上のホントの隣接ノードにすると、このマッチングは失敗する。なぜから、div#this の隣接ノードは空白を含むテキストノードだから。同様に次も失敗する。
<div id="this">...</div><!-- --><p>...</p>
これは直感にあわない。この問題を回避するために、Next-sibling範囲を次のように決める。
- コンテキストノード(基点)から弟(following)方向に兄弟をたどって、はじめて出現した要素ノードまでをNext-sibling範囲とする。複数の非要素ノード(pi, comment, text)が含まれるかもしれない。
- 要素が出現する前に兄弟リストが終わった場合は、最後の兄弟までをNext-sibling範囲とする。このとき、要素ノードは含まれないが、非要素ノード(pi, comment, text)が含まれるかもしれない。
- コンテキストノード自体が兄弟の最後のノードのときは、Next-sibling範囲は空となる。
次の例で、div#this に対するNext-sibling範囲のサイズは4となる。要素ノードが1個、非要素ノードが3個である。
<section> <div id="this">...</div> <!-- --> <p>...</p> </section>
Next-sibling範囲のリミットはサイズに関わらず1なので、マッチング成功は高々1回。
もう一度検索範囲の構造をまとめると:
- ノード集合: 空集合でもよい。
- 侵入的順序構造: 線形順序。
- 非侵入的順序構造: Descendant範囲以外では侵入的順序と同じ。
- リミット:Next-sibling範囲以外ではサイズと同じ(自明、無制約)。Next-sibling範囲では常に1。