Jintrick.netagenda2003年04月アーカイブ → 2003年04月19日

フラットな物語風XMLの差分に関するメモ

ISO-HTMLのような"フラットな"構造をもったXML文書の、各セクションを個別に更新した際、その差分をどうやって比較しようかという話です。

<h2>Section1</h2>
<p>para1</p>
<p>para2</p>

<h2>Section2</h2>
<p>para1</p>
<p>para2</p>

これは二つのセクションの構造を簡潔に表現したものです。「物語風XML(XHTML等)」では、要素名や属性値はメタデータ的な、付加情報的なものであり、XMLとして同一であるか否かを比較せずとも、その内容を比較すれば十分であると思われます。つまり物語風XMLにおいては、マークアップの修正は更新とは呼ばず、その内容の変更が更新と呼ばれるものと仮定します。

従って、各セクションの「内容」を参照することから始めます。

  1. 各セクションについて、DocumentFragmentを作成し、各ノード(例ではh2と二つのp)をappendChildします。
  2. その各DocumentFragmentについてこれをコンテクストノードとした相対ロケーションパス: descendant::text()を参照します。

具体的な方法はDOMとXPathの実装に依存しますが、この方法だと比較的直感的に参照できると思います。

その内容は、メタデータとして保持しておく必要がありますが、ここで問題となるのは、セクションの一意性です。折角内容を保持しても更新されたセクションとの対応関係が分からなければ利用できません。HTMLでいえばid属性を持たせれば良いのですが、これが実に鬱陶しい。文書を作成する上では見出しを考えるだけでも一苦労なのに、その上メタデータとしての識別子をも考えねばならないのは馬鹿げています。

海外(英語圏)では、見出しの語句をそのままアンダースコア "_" 等で連結したものをidにすることで自動化している例がありますが、日本語の場合、HTML等のフォーマットに変換する際に障壁になってきます。また、私は物語風XMLは直接編集したいので、ソースが汚くなってしまうことは避けなければなりません。id属性のような編集と無関係なものは、分離しておきたいのです。

ここで考えたのが、パブリックな位置で利用され得る普遍的な識別子と、ローカルで活用する識別子を分けてしまう方法です。

前者、つまりHTMLのid属性のような普遍的識別子は、秒単位の作成日時を元に作成します。後者は、識別子というよりも差分を比較する際のラベルとして利用するもので、見出しの文字列をそのまま利用します。両者はともに、XML文書内には記述せずにサイトマップなどのメタデータファイルに分離させて管理します。

このようにすることで、編集が楽になり、ソースはシンプルになり、見出しのちょっとした変更も行うことが出来るようになります。

注意点としては、一つのXML文書内に同一の見出しの登場が許されないため、例でいうh2要素をID型にしてスキーマでチェックする必要があるという点です。

つづく……かもしれない。...redesign in progress.

物語風XML
参照:dW : XML : データ用のXML: XSLスタイル・シート: プッシュ・スタイルかプル・スタイルか?

webmaster@jintrick.net
公開: 2003年04月19日
カテゴリ: DOM ,XPath ,ウェブデザイン