agenda 2003-09(下旬)

self軸をQNameによる要素型の検査に使う(XPath1.0)

最終更新
2003-09-30T16:05:48+09:00

自分自身(カレントノードやコンテクストノード)の要素型を調べる用途でself軸を使うことが出来ます。例:

<xsl:if test="self::html:image">
	<xsl:message terminate="yes">image要素型を検知</xsl:message>
</xsl:if>
<!-- 祖先要素に xmlns:html="http://www.w3.org/1999/xhtml" があると仮定 -->

カレントノードがXHTMLの名前空間のimage要素であるかどうかを、QNameを用いて調べていますが、同様の検査をself軸を用いずに行うと、次のようになります。

<xsl:if test="local-name() = 'image' and namespace-uri() = 'http://www.w3.org/1999/xhtml'">
	<xsl:message terminate="yes">image要素型を検知</xsl:message>
</xsl:if>

主に述語内で使うことになりそうです。

  • /descendant::html:blockquote/child::*[boolean(self::html:p) = false()]

これは、全blockquote要素の子要素の内、p要素でない要素を表現します。最後のステップにおいてコンテクストノードがp要素であるかどうかを、QNameを用いて調べています。

追記:属性は不可

self::QNameは、self::*のサブセットであると考えると分かり易いのですが、self軸の主ノード型は要素ノードです。従って、たとえカレントノードやコンテクストノードが属性ノードであったとしても、self::QNameで自分自身を示すことは出来ません。自分自身を表現するにはself::node()とするしかなく、QNameで属性型を検査することはできません。

追記:name()関数は使えない!?

name()関数を使うと、例えばname() = 'html:title' 等の式でそのノードの型をQNameにより判別できそうですが、これはソース文書(変換元のXML文書)においてある名前空間に関連付けられている名前空間接頭辞を知っている場合にのみ使えます。

妥当な二つのXML文書があったとします。ここで、一方はデフォルトの名前空間を用いており、もう一方は接頭辞fooを用いているとすれば、name()関数の戻り値は異なってしまいます。スキーマは名前空間接頭辞について規定できませんから、そのような特定の接頭辞に依存したスタイルシートはナンセンスだと思います。

document(ノード集合) の例(XSLT 1.0)

最終更新
2003-09-18T05:11:23+09:00

XSLT 1.0 のdocument関数が、唯一つの引数をもち、それがノード集合である場合について、例示します。今回は見た目の煩雑を避けるため、XPath式は省略記法を使用していますが、省略記法を推奨するものではありません。

次のような解析された(パース済み)XMLツリーがあったとします。

<Bookmark>
 <url>./object1.xml</url>
 <url>./object2.xml</url>
 <url>./object3.xml</url>
</Bookmark>

これに対して、次の式は何を返却するでしょうか:

  • document(/Bookmark/url)

前回document関数の概要で示した定義を再掲します:

  • あるdocument関数 が、唯一つの引数 A を持ち、A がノード集合 { a1, a2, .. am } である場合、その戻り値は、A に含まれる各ノード an (n = 1, 2, .. m) について、an の文字列値を第一引数とし、an のみ含むノード集合を第二引数にもつ document関数、即ち、 document(string({ an }), { an }) (n = 1, 2, .. m) の結果の和集合になる。

従って、document(/Bookmark/url)は次の 3つの式の和集合と等価です。

  • document(string(/Bookmark/url[1]), /Bookmark/url[1])
  • document(string(/Bookmark/url[2]), /Bookmark/url[2])
  • document(string(/Bookmark/url[3]), /Bookmark/url[3])

つまりdocument(/Bookmark/url) は次の式と等価です:

  • document(string(/Bookmark/url[1]), /Bookmark/url[1]) | document(string(/Bookmark/url[2]), /Bookmark/url[2]) | document(string(/Bookmark/url[3]), /Bookmark/url[3])

まず、document(string(/Bookmark/url[1]), /Bookmark/url[1])から見てみます。これは、string関数によって次のように展開されます。

  • document('./object1.xml', /Bookmark/url[1])

ここで、第一引数 './object1.xml' を相対URI、/Bookmark/url[1] というノードの Base URI を基底URIとして、絶対URIが導出されます。

Base URIは通常、そのノードが存在するXML文書のURIになります。そのノードが外部実体であった場合には、その実体のURIになります。従って、/Bookmark/url[1] の Base URIを知るには、解析前のXML文書を見なければなりません。

先ほど例示した解析済みXMLツリーは、実は次のようなXML文書の一部でした。


<?xml version="1.0" encoding="Shift_JIS"?>
<!DOCTYPE test [
 <!ENTITY fragment1 SYSTEM
  "./depth1/fragment1.xml">
 <!ENTITY fragment2 SYSTEM
  "./depth1/depth2/fragment2.xml">
 <!ENTITY fragment3 SYSTEM
  "./depth1/depth2/depth3/fragment3.xml">
]>

<Bookmark>
 &fragment1;
 &fragment2;
 &fragment3;
</Bookmark>

例えば&fragment1 は外部実体の参照で、SYSTEM識別子 './depth1/fragment1.xml' で表されるリソース<url>./object1.xml</url>が実体になっています。このXML文書の所在が http://www.example.com/ であったとすれば、相対URIの形をとっているSYSTEM識別子は http://www.example.com/depth1/fragment1.xml に解決されます。

/Bookmark/url[1]というノードの Base URIは、&fragment1; の実体のURIである http://www.example.com/depth1/fragment1.xml となります。

従って、document('./object1.xml', /Bookmark/url[1])における第一引数 ./object1.xml は絶対URI http://www.example.com/depth1/object1.xml に解決されます。

即ち、document('./object1.xml', /Bookmark/url[1])は次の式と等価です。

  • document('http://www.example.com/depth1/object1.xml')

同様にして、その他の二つのdocument関数:

  • document(string(/Bookmark/url[2]), /Bookmark/url[2])
  • document(string(/Bookmark/url[3]), /Bookmark/url[3])

これらも、次のように展開されると考えることが出来ます。

  • document('http://www.example.com/depth1/depth2/object2.xml')
  • document('http://www.example.com/depth1/depth2/depth3/object3.xml')

そして、この三つのdocument関数の結果の和集合が、最終的にdocument(/Bookmark/url)の結果となります。この場合、3つ文書のルートノードを含んだノード集合です。

クライアントサイドのXSLTを使った実験

ブラウザのXSLTプロセッサを利用した実験です。Windows版Internet Explore 6 で確認しましたが、object1 object2 object3 (順不同) と表示されれば成功です。

注意点

  • document関数で「取り込む」複数のXML文書のうち、一つでも整形式でないものがある場合、XSLTプロセッサはそれをエラーとします。
  • document関数で「取り込む」複数のXML文書については、解析が終了した順にノード集合に格納されるらしく、そのため順序に依存したスタイルシートを書くと危険です(MSXML)。

段組の利点 - 3つの情報ブロックがある場合

最終更新
2003-09-16T21:43:33+09:00

A, B, C という情報ブロックがあったとします。Aはサイトナビゲーション、Bはその文書のコンテンツ、Cは関連記事へのリンクを並べたものとし、左から、A, B, C という順に「段組」されて並べられています。しばしば標準的であると言われている構成です。

さて、閲覧者は何を読みに来たのでしょうか。当然、Bを読みに来ました。左右のA, Cを無視し、まずBを読みます。

閲覧者はBを読み終わりました。さて、この閲覧者がサイト内の別の文書を見たい(情報ブロックA)、或いは別サイトの関連文書(情報ブロックC)を見たいと考えたとしたら、どうでしょうか。ここで、段組の利点が明らかになります。即ち、とりあえずページの最上部に移動すれば、それぞれの情報ブロックの始点から眺めることが出来、選択が容易になります。

情報ブロックがB and ( A or C ) の二つしかないなら、ただスクロールの手間が増すだけなので、この利点は失われます。

情報ブロックCを否定

ただ、右(或いは左)に「関連記事へのリンク柱を設ける」という方法は、はっきりいって全然駄目です。何故なら、「どのようにその文書と関連しているのか」という最も重要な説明を妨げるからです。例えば、その「関連記事」のタイトルが長い場合、変なところで折り返されて一気に可読性が低下します。また、どのように関連しているのかをコメントすることも出来ません。実に読みにくくなります。閲覧者は、今読んでいるその文書との関連性を、ものすごく短い、あるいは読みにくいアンカー文字列から、読み取らなければなりません。

リンクする理由を読み取れないリンク、それは非常に価値の低い、広告に近いものです。

ハイパーテキストにおいて、関連している文書へのリンクはコンテンツの次に重要なものです。それを、あのような狭苦しい場所に押し込めることなど私にはできません。

情報ブロックAを疑う

縦に並べるサイトナビゲーションはどうでしょうか。これは、サイト内で一貫していることが重要です。一貫性のないサイトナビゲーション程紛らわしいものはありません。それらの維持管理に自信が無いなら、止めて置いた方が良いと思います。

私の場合、自分のサイトに閲覧者を封じ込めたくないというか、むしろどんどん別のサイトの関連文書を見てもらいたいと考えていますので、サイトナビゲーションは最低限に抑えます。文書の立場に立って考えた結果です。その文書にとって、自分が所属している(あるいは製作者に勝手に所属させられている)ウェブサイトのことなんか、別にどうだっていいのです。その文書の目的は、自分を理解してもらうことです(参照:ウェブサイトを否定するメモ)。もちろん自分のサイト内にも関連文書があるかもしれませんが、そのときは、他サイトのそれと同じように扱えば良い話です。

因みに、このサイトのパン屑ナビゲーションはサイト内における位置を示すことが目的であり、情報の具体性のレベルを示す為のものです。サイトの紹介を目的とするものではありません。

私はウェブサイトを軽視しているわけではありません。ウェブサイトをアピールする、適切かつ自然な、または唯一の普遍的な方法が、各文書の立場に立ってものを考えることであると信じています。その根拠、あるいは「何故文書を主体に考えねばならないのか」については、ここに書ききれない程の膨大な理由が存在しますので、また別の機会に書きます。

特殊な用語

文書の立場に立って考える
存在と存続、被理解を目的とする主体として文書を捉え、その目的を達成する方法を考えること

参考記事

何故左右マージンを小さくすべきなのか
「無駄なスペース」が何故無駄であるかを知らなければ、今回の記事を読む意味はありません。
段組廃止(スカンクワークス・2003年9月)
閲覧環境の変化によって使い物にならなくなる段組について等。
Hatena::agenda(2003-09-14)
スクロールを抑える目的とは矛盾する一部の段組について等。先日の私のコメント。
段組レイアウト(9月15日)
「段組はコンテンツを効率よく配置できる」という意見。「本文」が無く、情報ブロックそれぞれがコンテンツである場合に真。当サイトのホームページでもやっている。
段組の必要性 4月29日
広告を必ず表示させねばならない場合には、段組をしなければならないという、2002年4月に私が書いた記事だが、主題はそこにないので結構適当。