350 likes | 494 Views
XML のスキーマ書法 (2). 村田 真 日本 IBM( 株 ) 東京基礎研 / 国際大学. スキーマ言語. DTD, W3C XML Schema, RELAX NG. DTD の制定. W3C が XML 1.0 の一部として制定した SGML ( XML の原型)以来の長い歴史. DTD の構文. 要素型宣言 <!ELEMENT doc (sec*)> 属性リスト宣言 <!ATTLIST doc version CDATA #REQUIRED year CDATA 1999 >. DTD の問題点. 独自の奇妙な構文 拡張性の欠如
E N D
XMLのスキーマ書法(2) 村田 真 日本IBM(株)東京基礎研 / 国際大学
スキーマ言語 DTD, W3C XML Schema, RELAX NG
DTDの制定 • W3CがXML 1.0の一部として制定した • SGML(XMLの原型)以来の長い歴史
DTDの構文 • 要素型宣言 <!ELEMENT doc (sec*)> • 属性リスト宣言 <!ATTLIST doc version CDATA #REQUIRED year CDATA 1999>
DTDの問題点 • 独自の奇妙な構文 • 拡張性の欠如 • 構文解析がしにくく、ツールが作りにくい • 名前空間が扱えない • データ型がない
W3C XML Schemaの制定 • W3Cが2001年に制定した勧告 • Part 0, 1, 2の三部構成であり、総計400ページ • Part 0: 入門 • Part 1: 構造 • Part 2: データ型
主な機構 • 単純型(データ型) • 複合型 = 内容モデル + 属性宣言 • 継承(三種類) • 要素宣言(タグ名を型に関連付ける) • 属性宣言(属性名を単純型に関連付ける) • 名前空間とモジュール化のための機構
W3C XML Schemaの複合型 <xsd:complexType name="Address" > <xsd:sequence> <xsd:element name="city" type="xsd:string" /> <xsd:element name="zip" type="xsd:decimal"/> </xsd:sequence> <xsd:attribute name="country" type="xsd:NMTOKEN " use="fixed " value="US"/> </xsd:complexType>
W3C XML Schemaの問題点 • きわめて複雑 • 実装はいくつか存在するが,相互運用性に問題がある • OOXMLのスキーマはMicrosoftの実装でしか動かない • 基盤となる数学理論がない
RELAX NGの制定 • OASISのRELAX NG技術委員会とISO/IEC JTC1 SC34委員会 • ISO/IEC 19757-2
木正規文法 • 文字列言語ではなく木言語を使う • スキーマは木正規文法である • 生成規則は、n ::= a < exp > の形である • n非終端記号 • a終端記号 • exp非終端記号からなる正規表現 • XML文書はsentenceである
Chomsky階層 木言語 文字列言語 Context-Free Context-Free Regular Regular Local Local
木正規言語理論のもたらす利点 • 木オートマトンによる検証 • 数学的に厳密 • 小さな検証器 • ブール演算が可能 • スキーマの共通集合・和集合・差集合
デモ • ブログとAtomフィードの例 • Atom使用アプリのデモ(はてな、Firefox)
Atomスキーマ • RFC 4287
Atomのスレッド拡張(RFC 4685) • ブログ記事のスレッド、ブログのトラックバックによる関係を示す。 • 拡張部分 • in-reply-to要素 • rel="replies"のatom:link • total要素 • thr:count属性 • thr:updated属性
問題点 • スレッド拡張のスキーマは、Atom本体のスキーマから呼ばれていない。 • Atomフィード全体をAtom本体スキーマに照らして検証しても、拡張部分は検証されない。
スキーマのカスタマイズ方法 • 既存スキーマを直接編集する • 既存スキーマが改版されたとき、メンテナンスが困難。 • 既存スキーマを読み込んだ上で書き換えるスキーマを作る • テクニックを要する(とくにDTD)
方法1: 置き換え • 既存スキーマの定義文を、別の定義文で置き換える。どのスキーマ言語でも利用できる。
例 include "foo.rnc" { foo = bar } • foo.rncにあったfooの定義文は無視され、こちらの定義が用いられる。
方法2: 組み合わせ • 既存スキーマの定義文を生かしつつ、新しい定義文と組み合わせる。RELAX NGでのみ利用できる。
例1 include "foo.rnc" foo |= bar } • foo.rncにあったfooの定義文と、新しい定義文を、 choice(選択)で組み合わせる。
例2 include "foo.rnc" foo &= bar } • foo.rncにあったfooの定義文と、新しい定義文を、 interleave(順不同)で組み合わせる。
スキーマのスタイル • スキーマ書法にはいくつかのスタイルがある。 • どんな単位で定義文を書くかが各スタイルによって異なる。 • どのスタイルを採用するかによって、再利用性・保守性・可読性は大きく変わる。
有力なスキーマスタイル • Russian Doll(定義文をできるだけ分割しない) • Salami Slice(要素・属性が現れると定義文を分割する) • Venetian Blind(要素・属性の内容が現れると定義文を分割する) • Garden of Eden(Salami SliceとVenetian Blindの混合)
XML文書例 • <foo><bar><baz1>1</baz1><baz2>2</baz2><baz3>3</baz3></bar><sat><baz1>1</baz1><baz2>2</baz2><baz3>3</baz3></sat><mas><baz1>1</baz1><baz2>2</baz2><baz3>3</baz3></mas></foo>
Russian Doll • トップレベルでは、要素定義がひとつだけ存在する。他の定義は、すべてそのなかに埋め込まれる。 • default namespace = ""start =element foo {element bar {element baz1 { xsd:integer },element baz2 { xsd:integer },element baz3 { xsd:integer }},element sat {element baz1 { xsd:integer },element baz2 { xsd:integer },element baz3 { xsd:integer }},element mas {element baz1 { xsd:integer },element baz2 { xsd:integer },element baz3 { xsd:integer }}}
Salami Slice • 要素定義を用い、内容定義は用いない。要素定義に内容定義を埋め込む。 • default namespace = ""start = element foo { bar, sat, mas }bar = element bar { baz1, baz2, baz3 }sat = element sat { baz1, baz2, baz3 }mas = element mas { baz1, baz2, baz3 }baz1 = element baz1 { xsd:integer }baz2 = element baz2 { xsd:integer }baz3 = element baz3 { xsd:integer } • SGML時代からの伝統に基づいたスキーマ(Docbook, TEI, XHTML2など)では、Salami Sliceを原則として採用している。
Venetian Blind • 内容定義を用い、要素定義は用いない。内容定義に要素定義を埋め込む。 • default namespace = ""start =element foo {foo.content}foo.content =element bar { bsm.content },element sat { bsm.content },element mas { bsm.content }bsm.content =element baz1 { xsd:integer },element baz2 { xsd:integer },element baz3 { xsd:integer } • 最近のスキーマではVenetian Blindを採用しているものがある。
Garden of Eden • 要素定義と内容定義の両方を用いる。要素定義には内容定義を埋め込まない。 • default namespace = ""start =element foo {foo.content}foo.content =bar, sat, masbar = element bar { bsm.content }sat = element sat { bsm.content }mas = element mas { bsm.content }bsm.content = baz1, baz2, baz3baz1 = element baz1 { xsd:integer }baz2 = element baz2 { xsd:integer }baz3 = element baz3 { xsd:integer } • 最近のスキーマではGarden of Edenを採用しているものがある(Universal Business Languageなど)。
どのスタイルを採用するか(1) • Russian Doll • 簡明 • カスタマイズ困難 • 冗長性あり • Salami Slice • 伝統あるスタイルで、比較的理解しやすい • カスタマイズ可能 • 冗長性あり
どのスタイルを採用するか(2) • Venetian Blind • 比較的理解しにくい • カスタマイズ可能 • 冗長性はさほどない • Garden of Eden • 直感的でなく、理解しにくい • カスタマイズはきわめて容易 • 冗長性はない
問題 • Atom本来のスキーマをそのまま用いて、threading拡張スキーマを呼び出すようにカスタマイズせよ。 • Atom本来のスキーマを拡張しやすいように書き直せ。 • 書き直したスキーマをカスタマイズして、 threading拡張スキーマを呼び出せ。 • Threading以外の拡張について、スキーマを作成し、Atomスキーマ(書き直したもの)をカスタマイズして複数の拡張を同時に呼び出せ。
参考文献 • Atom解説, http://www.witha.jp/Atom/ • Bob DuCharme, “Your schema and the industry-standard schema”, http://www.idealliance.org/proceedings/xml05/abstracts/paper30.HTML • RELAX NG入門、http://www.kohsuke.org/relaxng/tutorial.ja.html