RELAX NG Compact Syntax
はじめに
書いてみるとRELAX NGってのは結構長い.XML形式ではないRELAX NG Compact Syntaxというのがあるので,そっちを使ってみることにする.RELAX NGでスキーマ記述でつくったRELAX NGのスキーマを書き換えることにしよう.
root要素
とりあえず,root要素と属性title,その直下にあるimg,content,p,ancherの各要素を書いてみる.参考までに,DTDも載せてみた.
| RELAX NG | RELAX NG Compact Syntax | DTD |
|---|---|---|
<element name="root">
<attribute name="title">
<text/>
</attribute>
<element name="img">
</element>
<oneOrMore>
<element name="content">
</element>
</oneOrMore>
<element name="p">
</element>
<zeroOrMore>
<element name="ancher">
</element>
</zeroOrMore>
</element>
|
element root{
attribute title{text},
element img{},
element content{}+,
element p{},
element ancher{}*
}
|
<!ELEMENT root (img,content+,p,ancher*)>
<!ATTLIST root title CDATA #REQUIRED>
|
キーワードelementは要素,attributeは属性を表している.キーワードの後ろに要素名,または属性名.要素名・属性名の後には{}をつけ,子要素やデータ型を記述する.
要素が順番に出現する場合は“,”で繋げる.“*”は0回以上の繰り返し,“+”は1回以上の繰り返しである.0もしくは1回は“?”となる.したがって,意味するところは以下の通りとなる.
- 要素rootには属性titleと子要素img,content,p,ancherがある.
- 属性titleは文字列.
- 子要素img,content,p,ancherはこの順番で記述する.
- contentは1回以上の繰返し.
- ancherは0回以上の繰返し.
img要素
img要素はwidth・height・src・alt属性を持つ空要素である.空要素なのでキーワードemptyをつける.
| RELAX NG | RELAX NG Compact Syntax | DTD |
|---|---|---|
<element name="img">
<attribute name="width">
<text/>
</attribute>
<attribute name="height">
<text/>
</attribute>
<attribute name="src">
<text/>
</attribute>
<attribute name="alt">
<text/>
</attribute>
<empty/>
</element>
|
element img{
attribute width{text},
attribute height{text},
attribute src{text},
attribute alt{text},
empty
}
|
<!ELEMENT img EMPTY>
<!ATTLIST img width CDATA #REQUIRED
height CDATA #REQUIRED
src CDATA #REQUIRED
alt CDATA #REQUIRED>
|
content要素
content要素はテキストとul要素の混合型である.ulはあってもなくても良い.
| RELAX NG | RELAX NG Compact Syntax | DTD |
|---|---|---|
<oneOrMore>
<element name="content">
<attribute name="href">
<text/>
</attribute>
<attribute name="name">
<text/>
</attribute>
<mixed>
<optional>
<element name="ul">
</element>
</optional>
</mixed>
</element>
</oneOrMore>
|
element content{
attribute href{text},
attribute name{text},
mixed{
element ul{
}?
}
}+,
|
<!ELEMENT content (#PCDATA|ul)*>
<!ATTLIST content href CDATA #REQUIRED
name CDATA #REQUIRED>
|
ulの下位要素として一つ以上のli要素と混合型のa要素があるので,全部書くとこうなる.
| RELAX NG | RELAX NG Compact Syntax | DTD |
|---|---|---|
<oneOrMore>
<element name="content">
<attribute name="href">
<text/>
</attribute>
<attribute name="name">
<text/>
</attribute>
<mixed>
<optional>
<element name="ul">
<oneOrMore>
<element name="li">
<mixed>
<ref name="a"/>
</mixed>
</element>
</oneOrMore>
</element>
</optional>
</mixed>
</element>
</oneOrMore>
|
element content{
attribute href{text},
attribute name{text},
mixed{
element ul{
element li{
mixed{
element a{
attribute href{text},
text
}
}
}+
}?
}
}+,
|
<!ELEMENT content (#PCDATA|ul)*>
<!ATTLIST content href CDATA #REQUIRED
name CDATA #REQUIRED>
<!ELEMENT ul (li+)>
<!ELEMENT li (#PCDATA|a)*>
<!ELEMENT a (#PCDATA)>
<!ATTLIST a href CDATA #REQUIRED>
|
全体像
こうしてできあがったのがこれ.
| RELAX NG | RELAX NG Compact Syntax | DTD |
|---|---|---|
<?xml version="1.0" encoding="utf-8"?>
<element name="root" xmlns="http://relaxng.org/ns/structure/1.0">
<attribute name="title">
<text/>
</attribute>
<element name="img">
<attribute name="width">
<text/>
</attribute>
<attribute name="height">
<text/>
</attribute>
<attribute name="src">
<text/>
</attribute>
<attribute name="alt">
<text/>
</attribute>
<empty/>
</element>
<oneOrMore>
<element name="content">
<attribute name="href">
<text/>
</attribute>
<attribute name="name">
<text/>
</attribute>
<mixed>
<optional>
<element name="ul">
<oneOrMore>
<element name="li">
<mixed>
<element name="a">
<attribute name="href">
<text/>
</attribute>
<text/>
</element>
</mixed>
</element>
</oneOrMore>
</element>
</optional>
</mixed>
</element>
</oneOrMore>
<element name="p">
<mixed>
<element name="a">
<attribute name="href">
<text/>
</attribute>
<text/>
</element>
</mixed>
</element>
<zeroOrMore>
<element name="ancher">
<attribute name="href">
<text/>
</attribute>
<element name="banner">
<attribute name="src">
<text/>
</attribute>
<attribute name="alt">
<text/>
</attribute>
<empty/>
</element>
</element>
</zeroOrMore>
</element>
|
element root{
attribute title{text},
element img{
attribute width{text},
attribute height{text},
attribute src{text},
attribute alt{text},
empty
},
element content{
attribute href{text},
attribute name{text},
mixed{
element ui{
element li{
mixed{
element a{
attribute href{text},
text
}
}
}+
}?
}
}+,
element p{
mixed{
element a{
attribute href{text},
text
}
}
},
element ancher{
attribute href{text},
element banner{
attribute src{text},
attribute alt{text},
empty
}
}*
}
|
<!ELEMENT root (img,content+,p,ancher*)>
<!ATTLIST root title CDATA #REQUIRED>
<!ELEMENT img EMPTY>
<!ATTLIST img width CDATA #REQUIRED
height CDATA #REQUIRED
src CDATA #REQUIRED
alt CDATA #REQUIRED>
<!ELEMENT content (#PCDATA|ul)*>
<!ATTLIST content href CDATA #REQUIRED
name CDATA #REQUIRED>
<!ELEMENT ul (li+)>
<!ELEMENT li (#PCDATA|a)*>
<!ELEMENT a (#PCDATA)>
<!ATTLIST a href CDATA #REQUIRED>
<!ELEMENT p (#PCDATA|a)*>
<!ELEMENT ancher (banner)>
<!ATTLIST ancher href CDATA #REQUIRED>
<!ELEMENT banner EMPTY>
<!ATTLIST banner src CDATA #REQUIRED
alt CDATA #REQUIRED>
|
名前付きパターン
RELAX NG同様,RELAX NG Compact Syntaxでも名前付きパターンを使うことができる.DTDには名前付きパターンはない.
| RELAX NG | RELAX NG Compact Syntax |
|---|---|
<?xml version="1.0" encoding="utf-8"?>
<grammar xmlns="http://relaxng.org/ns/structure/1.0">
<start>
<element name="root">
<attribute name="title">
<text/>
</attribute>
<ref name="img"/>
<oneOrMore>
<ref name="content"/>
</oneOrMore>
<ref name="p"/>
<zeroOrMore>
<ref name="ancher"/>
</zeroOrMore>
</element>
</start>
<define name="img">
<element name="img">
<attribute name="width">
<text/>
</attribute>
<attribute name="height">
<text/>
</attribute>
<attribute name="src">
<text/>
</attribute>
<attribute name="alt">
<text/>
</attribute>
<empty/>
</element>
</define>
<define name="content">
<element name="content">
<attribute name="href">
<text/>
</attribute>
<attribute name="name">
<text/>
</attribute>
<mixed>
<optional>
<element name="ul">
<oneOrMore>
<element name="li">
<mixed>
<ref name="a"/>
</mixed>
</element>
</oneOrMore>
</element>
</optional>
</mixed>
</element>
</define>
<define name="p">
<element name="p">
<mixed>
<ref name="a"/>
</mixed>
</element>
</define>
<define name="ancher">
<element name="ancher">
<attribute name="href">
<text/>
</attribute>
<element name="banner">
<attribute name="src">
<text/>
</attribute>
<attribute name="alt">
<text/>
</attribute>
<empty/>
</element>
</element>
</define>
<define name="a">
<element name="a">
<attribute name="href">
<text/>
</attribute>
<text/>
</element>
</define>
</grammar>
|
start=
element root{
attribute title{text},
img, ←要素でも属性でもなく名前付きパターン
content+, ←要素でも属性でもなく名前付きパターン
p, ←要素でも属性でもなく名前付きパターン
ancher* ←要素でも属性でもなく名前付きパターン
}
img= ←名前付きパターンの定義
element img{
attribute width{text},
attribute height{text},
attribute src{text},
attribute alt{text},
empty
}
content=
element content{
attribute href{text},
attribute name{text},
mixed{
element ul{
element li{
mixed {a}
}+
}?
}
}
p=
element p{
mixed{a}
}
ancher=
element ancher{
attribute href{text},
element banner{
attribute src{text},
attribute alt{text},
empty
}
}
a=
element a{
attribute href{text},
text
}
|
Trangで変換
これまで,手で書いてきたが,Trangを使うとDTDとRELAX NGとRELAX NG Compact Syntaxの三つのスキーマを変換しあうことができる.RELAX NGからRELAX NG Compact Syntaxを作ってみる.trang.jarがカレントディレクトリにある前提の場合,このようなコマンドになる.
$ java -jar trang.jar index.rng index.rnc
第一引数が入力ファイル,第二引数が出力ファイル.これらのファイルの拡張子で,入力・出力のスキーマを判定する.拡張子.rngがRELAX NG,.rncがRELAX NG Compact Syntaxである.