拡張子 | .sxml, .scm |
---|---|
MIMEタイプ | text/sxml |
タイプコード | TEXT |
種別 | マークアップ言語 |
SXMLは、XMLデータをS式の形式で記述、処理するための方法である。
SXMLとXMLの字句上の対応について、小さなサンプルのXMLを以下に示す:
XML | SXML |
---|---|
<tag attr1="value1"
attr2="value2">
<nested>Text node</nested>
<empty/>
</tag>
|
(tag (@ (attr1 "value1")
(attr2 "value2"))
(nested "Text node")
(empty))
|
上記の例から、以下の2つの点に気づくであろう:
SXMLとして具現化されたS式がXMLと似ていることから、XMLデータとプログラミング言語を密接に統合でき、結果としてアプリケーションにおけるXMLデータの処理が説明的で単純になる。
XMLのデータ処理言語は、例えばXPath、XSLT、XQueryが、W3 Consortiumにより提案されている。しかし、これらは、汎用的なプログラミング言語ではなく、アプリケーションの全てを実装するには不十分である[要出典]。 この理由により、ほとんどのXMLアプリケーションは、CやJavaのような伝統的なプログラミング言語、もしくはPerl、JavaScriptやPythonのようなスクリプト言語を用いて実装される。
2つの異なる言語(例えば、XPahtとJava)を組み合わせる試みは、インピーダンス・ミスマッチとして知られる問題を引き起こす。 インピーダンス・ミスマッチは、2つの側面からなる:
インピーダンス・ミスマッチは、複雑なコンバータと、2つの言語を結びつけるのに使用するAPI(例えば、DOM)を要求する。
インピーダンス・ミスマッチの問題を軽減もしくは消し去るために、Scheme関数プログラミング言語をXMLのデータ処理に使用する[1]事ができる:
Scheme(LISPの方言である)は、広い意味でのスクリプト言語である。Schemeは、実際に使用されている、最も洗練され、コンパクトなプログラミング言語の一つである: Schemeの標準の記述は、わずか40ページである。 Schemeは、高水準言語であり、高速なプロトタイピングに向いている。 さらに、Schemeプログラムは、一般的に、同じ機能のCプログラムよりも何倍もコンパクトである。
XMLとSXMLの字面は、とても似ている: 非公式には、SXMLは、XMLの開始/終了 タグを開き/閉じ 括弧で置き換える。 一方、SXMLは、S式であり、それゆえ、Schemeプログラミング言語の主なデータ構造であり、結果として、Schemeを経由して、簡単かつ自然に処理できる。
XML文書は、本質的に、ツリー構造である。 ルート要素の開始と終了タグは、文書の全ての内容を囲っていて、各内容は他の要素や任意の文字データを含む。 角ブラケットの文字列は、XML文書の外部表現である。 アプリケーションは、内部の形式で扱う: XML Information Set、もしくは、特別なものとして(例えば、DOM)として扱うべきである。 この内部形式を持ちいると、アプリケーションは、特別なデータ、もしくは、XMLツリーを別のツリーに変換したデータと位置づける事になる。
W3 Consortiumは、XML情報集合を抽象データセットとして定義した。情報集合は、整形式XML文書で利用可能な情報を記述する。
XML文書の情報集合は、多くの「情報項目 (information item)」から構成され、情報項目が表すのは、要素、属性、文字情報、処理命令、と、その他の文書の項目である。 各情報項目は、多くの関連付けられた属性を持つ。例えば、名前、名前空間URIである。 いくつかの属性 -- 例えば、子要素と属性 -- は、他の情報項目のコレクションである。 しかし、技術的には、情報集合はXMLに特化したものであり、他の半構造化データの書式、特にHTMLに大部分が適用される。
XML文書の構文解析は、XML情報集合のインスタンスを生成する一つの方法でしかない。
注意すべき事に、XML情報集合の勧告は、包括的なものをもたらすのではなく、最低限の情報と属性のセットを構築することである。 勧告の目的は、一貫性のある定義のセットを提供し、整形式のXML文書の中の情報を参照するのに必要な他の仕様でも使えるようにすることである。
XML情報集合勧告で定義される抽象データモデルは、W3コンソーシアムの全てのXML関連の仕様に適用可能である。 すなわち、ドキュメント・オブジェクト・モデルは、情報項目を扱うためのAPIと解釈できる; XPath data modelは、情報項目から派生するノードの概念を利用している、等。 DOMとXPathデータモデルは、それゆえ、2つのXML情報集合のインスタンスである。
XML情報集合勧告は、それ自体ではデータ構造や、情報項目へのアクセスのインタフェース (情報技術)に制限を設けていない。 それゆえ、XML情報集合から抽象データモデルへの別の変換方法が可能である。 例えば、XML情報集合を、ツリー構造と解釈し、"情報集合"と"情報項目"は、それぞれ一般的な用語である、"ツリー" と "ノード"と同じであると解釈するのは、役に立つ。
情報項目は、項目自身の属性のコンテナと解釈でき、そして、テキストの文字列(例えば、名前、名前空間URI)や、項目自身(例えば、XMLの子要素)も同様であるかもしれない。
情報集合は、それゆえ、ネストしたコンテナの階層である。 このようなコンテナの階層、つまりテキストの文字列と他のコンテナから構成されるコンテナの階層は、一般的にS式によって記述できる。なぜなら、S式は、リストのメンバーはアトムの値かS式自身であると、再帰的に定義されるからである。 S式は、簡単に、トラバースに適した内部表現にパースできる; S式には、簡潔な外部表記法があり、S式は、比較的容易に、手作業ででも、構築する事ができる。
SXMLは、XML情報集合の、S式による完全なインスタンスである。 情報集合のゴールは、全ての関連するデータの書式と、データの抽象化、データ同士の関連のコンテナ・スロットを提示することである。 SXMLは、S式で完全に具象化した、ネストしたコンテナを与え、情報項目と属性へのアクセス手段を供給する。 SXMLは、XPathとDOM(これらは、XML情報集合の2つの別のデータモデルでもある)の親戚である。 SXMLは、とりわけSchemeベースの XML/HTMLの記述、XPathクエリ、ツリーの変換に向いている。
XMLとSXMLは、それゆえに、XML情報集合についての、2つの文法的に異なった表現と考える事ができる。
前節で指摘したように、SXMLは、XML情報集合をS式の書式で完全にインスタンス化したものである。 本節でのSXMLについてのさらなる議論は、SXML仕様に基づくものである。
簡潔なSXMLの文法をEBNF記法にて以下に示す。
SXMLの<name>
は、単一のSchemeシンボルである。
[1] <TOP> ::= ( *TOP* <PI>* <Element> )
[2] <Element> ::= ( <name> <attributes-list>? <child-of-element>* )
[3] <attributes-list> ::= ( @ <attribute>* )
[4] <attribute> ::= ( <name> "value"? )
[5] <child-of-element> ::= <Element>
XML情報集合の一つの情報項目は、属性の集まりであるから、リストは、とりわけ項目を表現するのに好都合なデータ構造である。 リストの最初、Schemeの識別子は、情報項目の名前である。 多くの情報項目にとって、この識別子が、(拡張された)項目名である。 XML要素と表記される情報項目には、要素名で始まるリストが対応し、オプションとして属性のコレクションが続くことがある。 要素の項目のリストの残りは、要素の子要素、文字データ、処理命令、とその他の要素が順番に並んだものである。 全ての子要素は、一意である; 項目は決して、子要素を共有しない。たとえ、子要素が独自の内容を含んでいたとしてもである。
次の例は、XML要素とそれに対応するSXML記法での表現を説明したものである(<Element>
の表記をSXMLの文法でおこなった)。
XML | SXML |
---|---|
<WEIGHT unit="pound">
<NET
certified="certified">67</NET>
<GROSS>95</GROSS>
</WEIGHT>
|
(WEIGHT (@ (unit "pound"))
(NET
(@ (certified)) "67")
(GROSS "95"))
|
属性の値は、通常は文字列である; 属性は(HTMLにおいて)、ブーリアン型の場合は省略される事がある。例えば、上記の例では、"certified"属性の場合である。
属性の集まりは、情報項目の右の@の特別な名前でタグ付けされたものと解釈される。"@"の文字は、整形式XML文書の名前には現れない; それゆえ、<attributes-list>が要素を表すリストと取り違えられる事はない。 XML文書は、属性や、処理命令と他のメタデータで、要素がマークアップされる。
対照的に、SXMLは、要素とメタデータが統一的に、タグ付きリストで表現される。 RELAX NG -- XMLのためのスキーマ言語 -- も、属性を要素と共に統一的に扱う事を目的としている。 この統一的な処理は、ジェームズ・クラークによれば、言語の単純化についての、ある種の兆候である。 SXMLの有利な点は、全てのXMLの名前は有効なSchemeの識別子であるが、全てのSchemeの識別子が有効なXMLの名前ではないという点である。 この事実によって、@, *PI*, *TOP*のような管理用の名前を、XMLの名前との衝突の心配なしに導入できる。 さらに、XMLとSXMLの関係をWell-definedなものとする。 SXMLに変換されたXML文書は、(情報集合の範囲内で)等価なXML文書に再構築する事ができる。 さらに、情報集合仕様で与えられた実装の裁量範囲において、SXML自身は、情報集合のインスタンスである。
XMLの推奨は、処理命令 (PI) は、要素や文字データと区別できる事を指示している; 処理命令は、アプリケーションを通さなければならない。 SXMLにおいては、それゆえ、PIは専用の型である*PI*のノードで表現される。 XPath とDOM Level 2も、同様の方法で処理命令を扱っている。
XML文書と、それに対応するSXML表現のサンプルの両方を以下に示す。これらは、ネストしたXMLのタグとネストしたSXMLのリストの比較例を提示している。
SXML文書の方が、同等のXMLよりも僅かにコンパクトである事に注意してほしい。
XML | SXML |
---|---|
<?xml version='1.0'>
<di contract="728g">
<wt refnum="345">
<delivery>
<date month="6"
day="01"
year="2001"/>
<weight>783</weight>
</delivery>
<vehicle type="lorry"
number="A567TP99"/>
</wt>
<wt refnum="459">
<vehicle type="car"
number="25676043"/>
</wt>
</di>
|
(*TOP* (*PI* xml "version='1.0'")
(di (@ (contract "728g"))
(wt (@ (refnum "345"))
(delivery
(date (@ (month "6")
(day "1")
(year "2001")))
(weight "783"))
(vehicle (@ (type "lorry")
(number "A567TP99"))))
(wt (@ (refnum "459"))
(vehicle (@ (type "car")
(number "25676043"))))))
|
SXMLは、XML文書をパースした、抽象構文木であると考える事もできる。 XML文書もしくは、整書式になっているXMLの一部分は、自動的に、対応するSXML形式に、SchemeのXMLパース・フレームワークのSSAXを用いて変換される。
注目に値するのは、SXMLは、XML文書に含まれる全ての情報を表現する事である。コメント、XML名前空間や外部エンティティも含めて。 これらの事は、単純にするために本節では省かれているが、SXMLの仕様では検討されている事である。
例えば、簡易なXHTMLページは、以下のようなものがある:
<html xmlns="http://www.w3.org/1999/xhtml"
xml:lang="en" lang="en">
<head>
<title>An example page</title>
</head>
<body>
<h1 id="greeting">Hi, there!</h1>
<p>This is just an >>example<< to show XHTML & SXML.</p>
</body>
</html>
これをSXMLに変換すると以下のようになる:
(*TOP* (@ (*NAMESPACES* (x "http://www.w3.org/1999/xhtml")))
(x:html (@ (xml:lang "en") (lang "en"))
(x:head
(x:title "An example page"))
(x:body
(x:h1 (@ (id "greeting")) "Hi, there")
(x:p "This is just an >>example<< to show XHTML & SXML."))))
各要素のタグのペアは、括弧のセットに置き換えられる。タグの名前が終わりの部分で繰り返される事はなく、単にリストの最初のシンボルになるだけである。要素の内容が要素名に続き、内容は要素自身か、文字列である。XMLの属性については特別な文法はない。SXMLにおいては、属性は単純に別のノード、特別に@の名前を持つノードで、表現される。これが、実際の"@"タグと衝突する事はない。なぜなら、@は、XMLではタグの名前として許されていないからである。これは、SXMLで共通のパターンである: いつでも、タグが特別な状態や物事を示すのに使われ、そのタグはXMLでは使われる事はなく、その名前を使って有効なXMLの識別子を作る事はできない。
また他に、エスケープや他の特別な意味を持つ文字、&
実体参照や>
実体参照のような表記が必要ない事を見てとれる。全ての文字列の内容は、自動的にエスケープされる。何故なら、それらは純粋に内容と解釈でき、タグやエンティティを中に含まないからである。これはまた、自動的に生成された内容を中に挿入するがずっと容易であり、エスケープし忘れる危険を侵さずに、生成内容を別のユーザーに表示できる。(これらは、全ての種類のやっかいなクロスサイト・スクリプト攻撃や、他の頭痛の種を引き起こす)
本節では、SXMLの文法とS式の性質から差し引かれる、SXMLのいくつかの重要な特徴について考察する。
SXMLの属性リストのcdrは連想リストであり、それゆえ、SXMLが、LISPのプログラミングによって読み込まれる時、全てのSXMLの属性は、属性リストから、Lispのビルトインのassoc機能を用いて、変換する事ができる。
SXMLの統一的な、要素、属性、処理命令の表現は、クエリや変換をシンプルにする。 SXMLのデータモデルでは、属性や処理命令は、通常の要素から名前を消し去ったものように見える。 そのため、属性専用のクエリや変換関数は、冗長なものになる。何故なら、要素の名前を消した形の通常の関数が使えるからである。
このSXMLの要素と属性の統一的な表現は、特に実務において役立つ。 XMLの要素と属性の間の違いは、ぼやけてくる。 要素か属性のどちらを、現実の現場の情報の表現に使用するかは、しばしば流儀の問題であり、後で変更できる選択である。 データ構造内のこのような変更は、SXMLにおいては、単にひとつの階層のレベル(属性リスト)での追加/削除で表現できる。 この事は、SXMLのアプリケーションは最小の修正済む事を意味する。 SXMLの記述にとっては、属性と要素のわずかな違いは、構成内容が、属性リスト(特別なSXMLのノードである)に含まれている事と、ネストした要素を持てない事である。
例えば、もし、配達 (delivery) の重さ (weight) についてのデータの再構成が必要になり、最初はネストした要素だったものを属性で表現すると、SXMLの要素は、以下のようになる。
(delivery
...
(weight "789")))
から
(delivery
(@ (weight "789"))
...)
に変更。
このような、要素と属性の記述方法は、SXMLデータの再構成を単純にし、データ処理に用いられるクエリを統一的なものにする。
SXML文書は、本質的にツリー構造であるので、このツリーのノードに対して、SXML ノードの用語を導入する事により統一的な方法で表現できる。
SXMLのノードは、以下の単一の生成規則[N]のSXML文法で定義できる。 また、代わりに、SXMLノードは、2つの相互再帰的なデータ型を含むセット: [N1], [N2] と [N3]、として定義する事も可能である。 後者の場合、ノードは、自身の一番左のメンバーとして、ノードリストに対する名前を加える事によって構築される; ノードリスト自体は、ノードの(ソートされた)リストである。
[N] <Node> ::= <Element>
このような解釈は、SXMLのツリー構造と、S式による、情報項目の統一的な表現を強調する。
LISP系列のプログラミング言語の文法、特にSchemeは、データとコードの両方の表現に使われるS式に基づく。この事は、Schemeのプログラムが半構造化データとして扱われたり、その逆を可能かつ簡便にする。
SXML文書とそのノードはS式なので、これらをSchemeのプログラムの表現に使用できる。この事を可能にするのに十分条件は、SXMLツリー内のリストの最初のメンバーが関数であることである; マクロを使用すれば、より多くの事が可能になる。そして、リスト残りのメンバーは引数になり、引数は関数に引き渡される。SXMLの文法によれば、属性と要素名と特別な名前は関数に関連付けられなければならない。
これらの条件を満たす、SXML文書もしくはSXMLノードは、評価可能なSchemeプログラムとみなせる。例えば、eval関数を用いて評価できる。
例として、もし、para と boldが以下の様に関数として定義されているとする:
(define (para . x) (cons 'p x))
(define (bold . x) (cons 'b x))
この場合、次のSXML要素は
(para "plain"
(bold "highlighted")
"plain")
プログラムとして扱う事ができ、その評価の結果はSXML要素である:
(p "plain"
(b "highlighted")
"plain")
プログラムの評価の結果は、必ずしもSXMLの要素である必要はないことに注意すること。 主に、プログラムは、XMLもしくはHTML形式のソースのデータの表現を返す; もしくは、副作用、例えばSXMLデータを関係データベースに保存するかもしれない。
リストの表現の根本は、片方向リストであるため、ノードは、自身の前にある兄弟や親のノードへのアクセス方法がない。ほぼすべての、DOMとXPathのトラバース操作は、SXMLでも行き詰まる事なく可能であるが、親ノードからの各々のノードの位置や、トラバースした子ノードのインデックスや、現在のノードのパスは操作できない。
DOMの「NodeList.item」もしくは、XPathの「[] 」アクセサのような任意の位置のクエリには、向いていない。なぜなら、リストは、n番目のノードまでたどらなければならないため、この処理にはO(n)の計算時間がかかる。それに対して、ベクトルや配列のアクセスはO(1)ですむ。
実際、SXMLと、それに似たS式をXMLの表現するために用いたフォーマットは、シーケンシャル処理に向いている。例えば、SAXのイベント処理や、XMLへの属性の追加やシリアライズのようなものに向いている。可能な変換処理は限られており、前の兄弟や親のノードを必要としないものや、単純さを放棄して、スタック構造を使用しない変換処理のみである。
Detailed introduction, motivation and real-life case-studies of SSAX, SXML, SXPath and SXSLT. The paper and the complementary talk presented at the International Lisp Conference 2002.