気の向くままに辿るIT/ICT/IoT
XML

XML 文法 / Extensible Markup Language (XML) 1.0 (Fourth Edition)

ホーム前へ次へ
XMLの文法は?

XML 文法 / Extensible Markup Language (XML) 1.0 (Fourth Edition)

XML 文法 / Extensible Markup Language (XML) 1.0 (Fourth Edition)

 XMLHTMLとは違い、eXtensible Markup Language(拡張可能なマークアップ言語)として定義されていますが、この「拡張可能」というのは、XMLのタグや属性などを自分で(企業で、業界で、業界を超えた団体で、市区町村で、都道府県で、国で、世界で)独自に作成する事ができるという事です。

 XML自体は、一定の規則に沿ったテキスト文書ですから、これまでシステムに取り込む事ができなかったデータやシステムの違いから共有できなかったデータが共有できる事も意味し、非常に画期的な仕組みです。

 XML文書からHTMLを提供する事も可能ですし、XML1.0とHTML4が融合したXHTML1.0も生まれ、よりインタラクティブな世界が広がっています。

 以下XML文法は、W3Cのhttp://www.w3.org/TR/REC-xml/ 『Extensible Markup Language (XML) 1.0 (Fourth Edition)』2.1項~(英文)を当サイト管理人が2008年08月17日、意訳したものですが、構文解釈の違いや翻訳の違いが含まれるかもしれません。正式文書はW3C 各種仕様書(英語版)である事を予めご了承ください。

XML文法規則

XML文書2つの制約

 XMLの制約の1つは、『整形式制約』と『妥当性制約』(制約/constraint)でスーパーセットであるSGML[Standard Generalized Markup Language]、SGMLの元になったGML[Generalized Markup Language]や、HTMLとは違い、文法規則が厳格です。

整形式制約

 XMLの『整形式制約』は、「XMLは整形式文書/well-formedでなければならない」というものです。

妥当性制約

 XMLの『妥当性制約』は、「XMLは妥当な文書/validでなければならない」というものでXML文書はXML文法規則に沿った妥当な文書でなければならないという制約です。

XML予約語

 大文字小文字に関わらずXMLで始まる文字やXMLの予約領域名や予約語、リテラル文字で始まる文字列は利用できません。


XML
xML
XmL
Xml
...etc.

◆XML予約語例

 大文字を小文字問わず、XMLの予約領域上の以下の予約語「で始まる」文字列は利用できません。


letter([BaseChar]と[Ideographic]で定義された文字)で始まる文字列
ハイフン[-]で始まる文字列
コロン[:]で始まる文字列※1
ホワイトスペースで始まる文字列※2

※1 XML勧告の中の[Namespaces/名前空間]では、コロン[:]で始まる文字列を許可していますが、XML文書を作る人は名前空間以外の目的で使うべきではないとする一方でXMLパーサーは、これを許容する仕様でなければならないとあります。

詳細は、W3CのXML勧告『B Character Classes』(英文)参照。

◆XMLにおけるホワイトスペースの定義

※2 XMLでホワイトスペースは以下の通りです。

文字/16進16進表記文字が表す内容
09/#x9[HT]水平タブ
0A/#xA[LF]ラインフィード
0D/#xD[CR]キャリッジリターン
20/#x20ASCII CODEの空白文字

XMLリテラル文字

 XMLのリテラル文字はダブルクォーテーション("")またはシングルクォーテーション('')で括りましょう。

◆リテラル文字

 リテラル文字は以下の通りです。

実体参照と文字参照
/EntityValue
[^&%"']または&Name(名前領域)または%+ホワイトスペース+Name(名前領域)
属性値参照
/AttValue
[&NAME]または(16進数を表す)[&#]に続く数値[0-9]
システムリテラル
/SystemLiteral参照
[^"][^']
パブリックIDリテラル
/PubidLiteral参照
#x20 | #xD | #xA | [a-zA-Z0-9] | [-'()+,./:=?;!*#@$_%]
パブリック文字
/PubidChar実体
#x20 | #xD | #xA | [a-zA-Z0-9] | [-'()+,./:=?;!*#@$_%]

 但し、実体参照/EntityValueでは、「<」が単独の場合もクォーテーションで括る事が出来る事になっていますが、<!ENTITY mylt "<">のような記述は、「整形式文書/well-formedness」としてはエラーの原因になる可能性がありますから、このような使い方はしない方が賢明です。

XMLで利用できる文字

 XMLで利用できる文字は、UNICODEと[ISO/IEC 10646][ISO/IEC 10646-2000]で規定されている文字で、これらの文字コード上で定める制御文字と予約語、XML予約語と予約領域以外のすべてのテキスト文字です。

Unicodeの制御文字と予約語

 下記のUnicodeの制御文字と予約語は利用する事はできません。

[#x7F-#x84], [#x86-#x9F], [#xFDD0-#xFDDF],
[#x1FFFE-#x1FFFF], [#x2FFFE-#x2FFFF], [#x3FFFE-#x3FFFF],
[#x4FFFE-#x4FFFF], [#x5FFFE-#x5FFFF], [#x6FFFE-#x6FFFF],
[#x7FFFE-#x7FFFF], [#x8FFFE-#x8FFFF], [#x9FFFE-#x9FFFF],
[#xAFFFE-#xAFFFF], [#xBFFFE-#xBFFFF], [#xCFFFE-#xCFFFF],
[#xDFFFE-#xDFFFF], [#xEFFFE-#xEFFFF], [#xFFFFE-#xFFFFF],
[#x10FFFE-#x10FFFF]
XML利用可能文字範囲

 [#x]は16進数表記を表します。


#x9
#xA
#xD
[#x20-#xD7FF]
[#xE000-#xFFFD]
[#x10000-#x10FFFF]

 たとえ新たに追加される文字があったとしてもXMLプロセッサ(XMLを解釈できるブラウザ等)が解釈しなければならないと規定されています。

XMLの構成「文字データ」と「マークアップ」

 XMLというテキスト文書は、テキスト文字とマークアップから成っていますが、もちろん文字という文字全てがマークアップというわけではありません。

 マークアップとは開始タグと終了タグ、空要素タグ、実体参照、文字参照、コメント、CDATAセクションの区切り文字、文書タイプ定義(DOCUMENT TYPE)、解析指示、XML定義、テキスト定義と文書実体の外にあるものや内部にないマークアップという文書実体のトップレベルにあるホワイトスペースから成っているものとします。


◆XMLの構成

テキスト文字
マークアップ

 マークアップは、


◆マークアップ構成

XML宣言
DOCTYPE宣言
テキスト宣言
開始タグ
終了タグ
空要素タグ
実体参照
文字参照
コメント
CDATA(区切り文字によって列挙される)
PI命令/加工処理命令
ドキュメントルート実体に含まれるいくつかのホワイトスペース

から成っており、これらマークアップは内部でなく外部を指しています。

 [&]と[<]については、マークアップ区切り文字として、または、コメント内、加工処理命令中やCDATAでのみ、そのまま使う事ができます。

 つまり、これらアンパサンド文字(&)や左側ブラケット(<)は、マークアップ区切りやコメント内部、解析指示、CDATAセクションにある場合を除いてリテラル形式の中にあってはいけません。

 右側ブラケット(>)は、"&gt;"として使われるかもしれませんが、それがCDATAセクションの終端を表す"]]>"の一部でない時に限って、明確にクォーテーションで括るか文字参照してエスケープしなければいけません。

 もし、どうしても[&]と[<]を利用する必要がある場合には、文字参照するかそれぞれその文字をクォーテーションで括って"&amp;"や"&lt;"とする必要があります。


◆エスケープ方法

クォーテーション("&"や"<"のように個々に括る)
&#[0-9](10進数表記)
&#x[0-9a-fA-F](16進数表記)

 こういったケースで[>]を使う場合には、同様に引用符で括って["&gt;"]などと利用しますが、CDATAで終了を意味する


]]>

をエスケープした["]]>"]も含めて利用は、控えた方がよさそうです。

 言い換えれば、要素にはマークアップの開始区切り文字に相当する文字を含まないものが整形式の「要素の文字」であり、

 CDATAにはマークアップのCDATAの終了区切りに相当する文字列"]]>"を含まないものが整形式の「CDATAの文字」です。

 つまり、要素の中身である文字データとは、

マークアップの開始区切り文字が含まれていないもので且つ、CDATAの終端区切り文字である"]]>"が含まれていないもの

を指します。

 シングルクォーテーションとダブルクォーテーションが属性値として許されるのは、[']["]を[&apos;][&quot;]のように記述した場合です。

XMLのコメント

 XMLでコメントをする場合は、HTMLと同様に以下のようにします。


<!-- ~ -->

 または、


<!--



-->

とします。

PI

 PIとは、Processing Instructionsで直訳すれば加工処理命令といったような意味合いですが、要するアプリケーションが使えますよという事です。

 PIにはPI Targetという概念があり、大文字小文字を問わず[xml]で始まるとあり、style指定の


<?xml-stylesheet ?>

 があります。

 つまり、この勧告では、PIはXMLの仕様上使われる事が想定されており、XML1.0勧告ではPIについてここまでの記述しかありません。

 しかし、アプリケーションが使えるという点では、XML仕様策定上だけでなく一般にこのPIが使えると便利になる側面も多いと思われますが、純粋なテキスト文書を目指すXMLとしては一般に公開するにはいくつか課題もあると思われます。

CDATA

 CDATAは、テキストであればほぼ全て記述できるスペースでここにSTYLEやSCRIPTの指定もできます。


<![CDATA[<tag><xxxxx>&nbsp;xxx&trade; &copy;~</xxxxx></tag>]]>


<![CDATA[

<tag>
<xxxxx>&nbsp;xxx&trade; &copy;~</xxxxx>
</tag>

]]>

のように記述します。

CDATA開始デリミタ(区切り文字)

<![CDATA[

 但し、前述のXML予約語で触れたとおり、CDATAの終了デリミタにあたる

CDATA終了デリミタ

]]>

]]>を意味する16進数表記の「5D5D3E」の並び

を記述する事はできません。

Prolog

 Prologは、XML文書の最上段に記述する決まり事に沿った宣言で仕様上はDOCTYPE宣言の上位の概念で以下の情報から構成されています。

PrologプロローグXMLDecl? Misc* (doctypedecl Misc*)?
XMLDeclXML宣言'<?xml' VersionInfo EncodingDecl? SDDecl? S? '?>'
VersionInfoバージョン情報S 'version' Eq ("'" VersionNum "'" | '"' VersionNum '"')/* */
Eq等号[=]または[ = ]
VersionNumバージョン番号([a-zA-Z0-9_.:] | '-')+
Miscコメント | PI | ホワイトスペース

 プロローグでは、[コメント | PI | ホワイトスペース]を記述し、オプションとして[XML宣言]があり、[DOCTYPE宣言]と[ホワイトスペース]を書いてもいいよという事です。

doctypedeclDOCTYPE宣言'<!DOCTYPE' S Name (S ExternalID)? S? ('[' (markupdecl | DeclSep)* ']' S?)? '>'
EncodingDeclエンコーディング/文字コード宣言'encoding' = "EncName" | 'EncName'
SDDeclstandalone= 'yes' | 'no'を更にシングルまたはダブルクォートで括る
Sホワイトスペース前述ホワイトスペースの項参照
EncName文字コード名[A-Za-z] ([A-Za-z0-9._] | '-')*

 同様にXML宣言は、


<?xml



?>

で括った


<?xml~?>

の「?」の部分に


<?xml version=""?>

または

<?xml version=''?>

のようにダブルまたはシングルクォーテーションで括った[バージョン番号]を記述しますが、[バージョン番号]は必須でアルファベットの大文字小文字と[.]ピリオドと[_]アンダースコアと数字の組み合わせか(または、[-]ハイフンの指定)が使えるので


<?xml version="1.0"?>

といった(現行はこの"xml1.0"のみ)記述ができ、オプションとして[文字コード](文字コードはアルファベットの大文字小文字で始まり、任意数のアルファベットや数字、アンダースコア、ピリオドまたは'-'ハイフンを続けて記述)を指定して


<?xml version="1.0" encoding="UTF-8"?>

としたり、更にオプションとして[スタンドアローン]を指定して


<?xml version="1.0" encoding="unicode" standalone="yes"?>

と記述する事ができ設定の終わりと[?>]間にホワイトスペースが入ってもよいことになっています。

 [standalone]は[yes][no]の二者択一で[yes]を選択すると外部DTDを使わないという意味になり、そのままXMLプロセッサからアプリケーションに渡されます。

 外部マークアップ定義は外部サブセットやパラメータ実体の中でマークアップ定義として定義されます。(ただ、妥当性検証をしないプロセッサは、こうした情報を要求しません)

 [no]を選択した上で外部文書や外部実体参照があったとしても、その外部文書や外部実体が存在する旨が示されるだけで[standalone]で設定した[no]という値が[yes]というステータスに変わるわけではありません。

DOCTYPE宣言

 XMLのDOCTYPE宣言は、Prolog(XML宣言含む)の直後に記述する事になっており、[<!DOCTYPE]と[XML文書の名前]が必須となっていて[サブセット(DTD)]を含むこともでき、DTDは、内部DTDと外部DTDがありますが、どちらか一方でも両方でも利用する事ができます。


<!DOCTYPE XML文書の名前>


<!DOCTYPE XML文書の名前 "xx.dtd">

 [サブセット(DTD)]には、[%]+[ホワイトスペース]で始まる文字列か、要素タイプ定義、属性リスト定義、実体定義、表記定義のいずれかを記述します。

 更にDOCTYPE宣言には、オプションで[外部ID](xx.dtdが外部DTDである場合に定義されているURIを含む定義がなされた名前)を設定する事ができるようになっています。


<!DOCTYPE XML文書の名前 [外部ID] "xx.dtd">

 パラメータ実体参照はDTDのどこかに定義があれば認識されますが、内部サブセットで定義する事はできません。

 これは、XMLの『妥当性制約』と『整形文書制約』によるものです。

 内部サブセットから参照している外部サブセットに含まれる実体参照は可能で妥当性制約では、


◆妥当性制約

DOCTYPE宣言に使われる名称はルート要素の要素タイプと一致していなければならない。

パラメータ実体の代替テキストを記述する場合はマークアップ定義にネストされていないければならない。

 である一方、整形文書制約では、


◆整形文書制約

内部DTDの中のパラメータ実体参照は、マークアップ定義と一緒に記述される場合があったとしてもマークアップ定義の内側にあってはならない。
(あくまで内部DTDでの話であり外部実体参照や外部DTDの場合は別)

外部DTDは当然、外部DTDとして定義されていなければならない。

%とホワイトスペースに続くパラメータ実体参照の代替テキストは、外部DTDと一致しなければならない。

内部DTD同様、外部DTDや外部実体参照は各種マークアップ定義で許されているマークアップ定義に沿う完璧なものでなくてはならない。

とあり、妥当性制約ではマークアップにネストされなければならないと定義されていて内部DTDでパラメータ実体設定ができそうですが、整形式文書としては認められないので整形文書である事が大前提であるXMLでは内部DTDで定義されたパラメータ実体参照が利用できない事になるからです。

 ここまででXML宣言を含むプロローグ(の内、必須はXML宣言)とDOCTYPE宣言を記述し、タグを作成した場合(ここでは<ostype>)のサンプルは


<?xml version="1.0" encoding="euc-jp"?>
<!DOCTYPE ostype TYPEDEC "oskind.dtd">
<ostype>OS type is Windows OS.</ostype>

のようになり、この場合、外部DTDなので[oskind.dtd]のURIと[ostype]は[TYPEDEC]で定義されていなければなりません。

 これを内部DTDで実装する場合には次のようになります。


<?xml version="1.0" encoding="euc-jp"?>
<!DOCTYPE ostype [
    <!ELEMENT ostype (#PCDATA)>
]>
<ostype>OS type is Windows OS.</ostype>

 もし内部DTDと外部DTDが両方指定するような場合には、常に内部DTDは外部DTDより先に記述しておく必要があります。

 その大前提の環境(この前提が崩れると整形文書制約に反する)では外部DTDよりも内部DTDが優先されます。

ホワイトスペース処理

 XML文書を編集していると[tab][space][空行]を目にする事も多いですが、これらがあるから可読性が増しているという事実があります。

 これらのホワイトスペースは文書をやり取りする(という行為)上では特別な意味があるわけではありませんが、詩集やプログラムコードのように重要な意味を持つホワイトスペースはむしろ保持する必要があります。

 妥当性検証プロセッサは、要素内にホワイトスペースがあった場合には、それらのホワイトスペースも含めてアプリケーションに渡さなければなりません。

 XMLプロセッサは文書内の全ての文字を常に保持する必要がありますが、マークアップはアプリケーションに渡すものではありません。

 もし、[xml:space]と名付けられた特殊な属性があった場合、要素内に混じって記述されるケースもあるかもしれませんからアプリケーションは常にホワイトスペースを保持しなければならないのです。

 妥当な文書としては、こうした属性を使うのであれば、予め定義されていなければなりません。

 こうした特殊な属性を利用する場合には、定義する際に[default][preserv]の一方または両方を列挙型の[ATTLIST]で次のように明記しなければなりません。


<!ATTLIST 属性名 'default' 'preserv' >

<!ATTLIST 属性名 'default' >

<!ATTLIST 属性名 'preserv' >

または


<!ATTLIST 属性名 #FIXED 'default' >

<!ATTLIST 属性名 #FIXED 'preserv' >

 XMLプロセッサは、この設定が[default]になっていたらアプリケーション既定のホワイトスペース処理モードでこの属性を扱い、[preserv]であれば、全てのホワイトスペースを保持してアプリケーションに渡します。

 この定義は、他の[xml:space]というインスタンスで覆されない限り、その記述された要素が存在する文書内で有効です。

 これは[xml:space]に含まれる値がいずれも[default][preserv]のいずれかまたは両方の指定通りにならなければならないという意味ではありません。

 というのもこうした指定があっても定義違いや値自体が間違っている場合などに対処する必要があるでしょう。

 この場合アプリケーションの挙動としてはいくつか考えられます(ので特定はされていません)が、エラーを出力するだけかもしれませんし、再度定義を検索して識別しようとするかもしれませんし、間違った値をアプリケーションに渡すかもしれませんし、アプリケーションがその値を無視したり、排除したりするかもしれません。

 この点についてはいくつかのXML文書から成るルート要素が、値が認知されていたり、既定値として定義されていない限り、シグナルを持つ事を考えています(アプリケーションのスペース処理を意図しているわけではなく)。

行終端処理

 XML文書解析においてもファイル検索をする上で行を判断するのが便利な方法で、この行というのは[CR/キャリッジリターン][LF/ラインフィード]単独やこれらの組み合わせを終端としています。

 アプリケーション処理を単純化する為にXMLプロセッサは、[CR][LF]から成る行終端(改行)を全て連続しないひとつの[LF]に置き換えなければなりません。

言語統一

 文書と内容が何語で書かれているのかを示す[xml:lang]という特殊な属性があり、XML文書やXML文書中に含まれる要素や属性について国や地域の言語を明記する事ができます。

 妥当な文書ではこうした属性を使う場合には予め定義されていなければなりませんが、この属性に設定する値は[IETF RFC 3066]で定義済みです。

 [xml:lang]属性は他の[xml:lang]インスタンスで上書きされない限り有効で、もし[xml:lang]属性の設定が空[""]だった場合には、その前に[xml:lang]があればその設定が有効になりますし、なければ[xml:lang]属性を指定していないのと同じ状態になります。

 アプリケーションは、この[xml:lang]属性でXML文書やXML文書に含まれる要素や属性、その設定値などを[xml:lang]属性で指定された言語として認識するものとします。

 XML文書全体の言語を指定する場合には、


xml:lang CDATA 定型指定

つまり

xml:lang CDATA 'ja'

 とすればよいのですが、それとは別にこの[xml:lang]属性を利用すると部分的に言語を変更する事もできます。

 その場合には列挙型の属性指定[!ATTLIST]で


<!ATTLIST xml:lang CDATA 'en'

のように指定する事ができ[CDATA]の部分には要素の名前を入れるとXML文書全体としては「日本語」でこの要素内の言語は「英語」のように使い分ける事ができます。

物理的な構造

 XML文書はいずれもひとつまたは複数の


要素

を持っていて


開始タグと終了タグ

または

(要素がカラの)空要素タグ

があり、それぞれの「要素」は


「タイプ」
「識別できる名前」([GI/generic identifier]として識別される事も)
「列挙型の属性」

を持っていて、「属性」はそれぞれ


「名前」
「値」

を持っています。

 これらは、要素や属性の名前であってアプリケーションの仕様や使い方を限定するものではありません。

 但し、大文字小文字に関わらず[xml]で始まる名前などはXML標準化における現在または将来的に予約された名前なので使う事はできません。


◆整形文書制約

要素の終了タグの名前は、開始タグの「要素タイプ」と一致していなければなりません。


◆妥当性制約

名前が要素タイプと一致している要素定義と一致した定義で次のようなケースであれば妥当です。


◆注記

・定義がEmptyと一致するという場合には、実体参照、コメント、PI、ホワイトスペースなど何もない状態を指す

・定義との一致とは、開始タグと最初の子要素の間や子要素同士の間、または最後の子要素と終了タグの間にある付加的なホワイトスペースやコメント、PIを持つ文書様式によって記述された子やそれに続く子要素である場合です。
 CDATAセクションには、ホワイトスペースや実体の参照が含まれます。
 代替テキストは、文字参照の展開で、ホワイトスペースは終端のホワイトスペースとは一致しません。
 ですからこの位置にホワイトスペースがあってはなりません。
 しかしながら、内部実体を参照する場合にリテラル値が含まれていると文字参照の展開の結果としてホワイトスペースが一致する場合があります。

・PCDATAにおける定義との一致とは、その文書が代替テキストで実体参照を置き換えられた後、文書モデルの中のCDATAを含む文字データやコメント、PI、子要素のタイプと名前との一致です。

・何かが定義と一致するという状態は、(その文書が代替テキストで実体参照を置き換えられた後)、文書モデルの中の文字データやCDATA、コメント、PI、子要素のタイプが予め定義されているという状態を表します。

開始タグと終了タグと空要素タグ

 開始タグと終了タグの名前は、属性にタイプを持たせる事ができるようになっています。

 開始タグ、終了タグの名前と属性のペアは要素の属性の特性として参照されます。

 このそれぞれの名前が属性の名前として参照され、開始タグや空要素タグにある属性自体は重要ではなく重要なのは属性の中身である属性の値です。


◆整形文書制約 / 属性値

属性の名前は同じ開始タグと終了タグの中に2つ以上記述してはいけません。


◆妥当性制約 / 属性値タイプ

属性は値が定義されたタイプでなければならず(文字タイプなら文字、数値なら数値)且つ属性自体が定義されていなければなりません。


◆整形文書制約 / 外部実体参照不可

属性を外部実体参照によって、直接的、内部的に参照したりする事はできません。


◆整形文書制約 / 属性の中に<があってはならない

いかなる実体の代替テキストであっても、属性値として直接的、内部的に参照される実体には、左側ブラケット[<]があってはいけません。

 開始タグと終了タグは、


<tag_name 属性>

</ tag_name>

のように記述し、開始タグと終了タグの名前(ここでは[tag_name])が一致していなければなりません。

 この開始タグと終了タグの間に記述されるテキストは、element's content(要素の内容)と呼ばれ、ここはテキスト文字であれば基本的になんでも記述する事ができます。

 element's content(要素の内容)に何も指定されていなければ、「要素はカラ」であるといい、開始タグの直後に終了タグが来る事になりますが、この時に「空要素タグ」を利用する次のような記述方法があり、


<hr />
<br />
<img src="" />

のようにタグの[>]の前に[/]を記述します(<br><br/>のような記述もできるとありますが<br/>の方がスマートでしょう)。

 「空要素タグ」は、element's content(要素の内容)がない(例えば上記HTMLタグなど)いくつかの要素の為に使われる場合もあり、[EMPTY]というキーワードを使っている定義があるないに関わらず利用する事ができます※

 「空要素タグ」は、様々な環境で全体として正しい挙動をするというXMLの利用を考えた場合にも有効なので使われるべきタグであり、(※)必ずEMPTY定義をしてから利用するべきです。

要素タイプの定義

 XML文書中の要素の構成には妥当な目的の為に要素タイプと属性リスト定義を使用した制約があります。

 要素タイプは属性の内容を定義するものです。

 要素タイプはその要素の「子要素」に記述できる要素タイプの制約として使われる事も多いと思われ、XMLプロセッサがユーザオプションで定義が見つからないという警告を出す事もあるかもしれませんが、この場合は、エラーではありません。

要素タイプ定義

 要素タイプは以下のように記述します。


<!ELEMENT br EMPTY>
<!ELEMENT p (#PCDATA|emph)* >
<!ELEMENT %name.para; %content.para; >
<!ELEMENT container ANY >

要素内容

 要素タイプが(文字情報ではなく)子要素を持っている時、要素タイプには要素内容があるといい、付加的に(終端ではない)ホワイトスペースで区切られる事があります。

 こうした場合、子要素があってもいいのかどうか、子要素のタイプが許容されるのかは、要素内容モデル[content model]を含む制約という単純な文法規則によって決められています。

 この文法規則は、タイプ名と子要素の内容を表す端的な文字列を[|]で区切った選択肢または[,]で区切った複数指定ができるものとします。


<!ELEMENT spec (front, body, back?)>
<!ELEMENT div1 (head, (p | list | note)*, div2*)>
<!ELEMENT dictionary-body (%div.mix; | %dict.mix;)*>

 複数選択リストの場合、複数選択リストがあるべき場所に要素内容があってその要素内容の中に複数選択リストを表すリストが存在するという事もあり得ます。

 [,]で区切った複数指定の場合は、複数選択リストで指定した順番で要素内容に記述されなければなりません。

 名前に続く付加的な文字列やこれらの情報または、このリストが有効な指定範囲内でこれらの要素やリスト中の文字列が1回または1回以上、もしくは0回または0回以上、更には同じものが出てくることはないのか、もう1回出てくる場合もあるのかどうか?という点に悩むケースも想定されます。

 このように演算子が表現しきれない点があるので(その点を考慮して)[|]や[,]を使って選択肢や複数指定をした場合には、その要素やリスト中の文字列に該当する子要素は、それぞれ必ず1つはあるものとします。

 この取り決めと意味合いは、こういう特殊ケースと全く同一のケースがあればそのXML仕様にのみ適用されるものとします。

 要素の内容がcontent model(要素モデル)と一致するというのは、次のようなケースとします。


要素モデルの解析とトレースができ、コンテンツモデル(内容モデル)中の要素タイプに対してそこに出てくるそれぞれの要素が複数指定文字列や選択肢で指定したものと一致する場合に限って有効

であるものとします。

 もし内容モデルが、内容モデル中の要素タイプが1回以上あれば可とする場合はエラーとします。


◆妥当性制約 / Proper Group/PE Nesting

パラメータ属性代替テキストはカッコ()で括ってグループ化し、正しくネストされなければならない。
これはつまり、カッコの開始[(]や終了[)]が、[|]や[,]の選択肢や複数指定またはその併用の中にある場合、それは、代替テキストに含まれているということであり、この場合、いずれも同じ代替テキストの中に記述されていなければなりません。

様々な環境で全体として正しい挙動がなされる為に、もしパラメータ実体が選択肢や複数指定やその併用されたものを参照している場合には、その代替テキストは少なくとも1つ以上の空白のない文字であるべきで、代替テキストの最初か最後の空白のない文字を[|]や[,]でつなぐべきものとします。

混合内容(Mixed Content)定義

 混合内容とは、要素タイプが文字情報を含んでいる場合や付加的に子要素に付随してところどころに入っているといった場合を指すものとします。

 このケースでは子要素のタイプが制約されている事もありますが、だからといってそうした指定や出現回数が必ずしも指定されているとは限らないものとします。

 混合内容は以下のような記述になっています。


<!ELEMENT p (#PCDATA | a | ul | b | i | em)*>
<!ELEMENT p (#PCDATA | %font; | %phrase; | %special; | %form;)* >
<!ELEMENT b (#PCDATA) >


◆妥当性制約 / タイプ名の重複は不可

この時、1つの混合内容中ではその名前は1回しか使う事ができません(名前が重複してはいけません)。

属性リスト[Attribute-List]の定義

 属性は、必ず要素とペアになっていて名前と値で関連付けられているものとします。

 例えばHTMLのtableのように見た目の構成だけではなく、これによって要素が持つ属性の名前を見れば属性値がどんな意味を持つのかがわかるようになります。

 属性は、必ず要素とペアになっているわけですから、開始タグや空要素タグの外にあってはいけません。(属性の設定方法は『開始タグと終了タグと空要素タグ』参照)

 属性リスト[Attribute-List]は、例えば次のようなケースで利用される事が想定されます。


要素タイプで与えらた条件に付随する属性を指定する定義
属性に対する制約事項
属性の既定値

 属性リスト[Attribute-List]は、固有の名前とデータタイプと要素タイプで与えられた条件に付随するそれぞれの属性に既定値を持っているものとします。

 属性リスト[Attribute-List]は、


<!ATTLIST ~

のように記述され、属性定義のルールでは、「~」部には、「要素のタイプ」を記述します。

 この時、XMLパーサーはユーザーオプションで「定義されているはずの属性定義が定義されていません」といった警告を発する場合があるかもしれませんが、これはエラーではありません。

 「属性定義」ルール上の名前というのは純粋に「属性の名前」であって、この場合は「属性リスト定義」ルール上の「要素のタイプ」ではありません。

 要素タイプで提供される属性リストが複数存在するケースがあった場合は、併合(両方うまく適用)するものとします。

 全く同一の要素タイプで提供される属性リストが複数存在するケースがあった場合は、最初に定義されたものが有効で後に定義された同一の定義は無視されるものとします。

 様々な環境で全体として正しい挙動がなされるという観点から、DTDの作者は、属性リストを1つ選択するケースや、多くの作者は、属性リスト中のそれぞれの属性の名前に一致する属性定義を選択するケースなどが想定されますが、少なくとも1つの属性リストごとにそれぞれ属性定義がなされた状態にあるものとします。

 様々な環境で全体として正しい挙動がなされるという観点から、XMLパーサーがユーザーオプションとして「属性リスト定義や属性定義が1つ以上ある」という警告を発する場合があるかもしれませんが、この場合はエラーではありません。

属性タイプ[Attribute Types]の定義

 XML属性タイプには以下の3種類があります。


文字列型
トークン型
列挙型

 文字列型(CDATA等)は、その値の中にいくつかのリテラル文字が含まれている場合があるかもしれません。

 トークン型(ID、IDREF、IDREFS、ENTITY、ENTITIES、NMTOKEN、NMTOKENS等)は、それに比べるともっと制約されたものとします。

 妥当性制約は、全ての属性を標準化した後に評価されるものとします。


◆妥当性制約 / ID属性

IDは決められた文字を使った型で記述されなければなりません。
ID名はそのタイプ固有の値としてXML文書中で1回だけ利用できるものとします。


◆妥当性制約 / 要素タイプごとの各ID属性

要素タイプ固有の属性であるID属性は1回だけ利用できるものとします。


◆妥当性制約 / ID属性の既定値

ID属性は[#IMPLIED]または[#REQUIRED]でなければなりません。


◆妥当性制約 / IDREF/IDREFS属性

IDREF/IDREFSというタイプの値は、決められた型で構成された文字列でなければならず、IDREF/IDREFS名の構成文字列は、XML文書にある属性のIDと一致していなければなりません。


◆妥当性制約 / 実体名

ENTITY/ENTITIESというタイプの値は、決められた型で構成された文字列でなければならず、ENTITY/ENTITIESでは、それぞれDTDで定義された解析されない実体名(参照ではなく展開されたものが実体なので解析されない)と一致していなければなりません。


◆妥当性制約 / 名前トークン

NMTOKEN/NMTOKENSというタイプの値は、決められた型で構成された文字列でなければなりません。

 列挙された属性は、定義された値のリストであるものとします。

 列挙された属性タイプには、[NotationType]と[Enumeration]という2種類があります。


[NotationType]
'NOTATION' ( ~ )
'NOTATION' ( ~ | ~ )


[Enumeration]
( ~ )
( ~ | ~ )

 [NOTATION]という属性の特徴は、システムに関連付けられたDTDで定義されているか、パブリックな識別子であって属性はいずれかの要素として解釈されて利用されるものとします。


◆妥当性制約 / Notation属性

Notation属性の値は、Notation(表記)定義で定義された名前と一致していなければならず、全てのNotation属性名はNotation定義で定義されていなければなりません。


◆妥当性制約 / 要素ごとのNotation属性

要素タイプにはNotation属性は1つで、複数あってはいけません。


◆妥当性制約 / Empty要素のNotationは不可

NOTATIONというタイプの属性は、要素タイプで[EMPTY]と定義されたものではいけません。


◆妥当性制約 / トークンの重複は不可

属性定義で単独のNotationTypeであるnotation名や同様に属性定義で単独のEnumeration中のNmTokensは、別個でなければなりません。


◆妥当性制約 / Enumeration

Enumerationは、定義されたNmTokensのひとつのNmTokenと一致しなければなりません。

属性の既定値

 属性定義は、XMLプロセッサが定義された属性がXML文書中にない場合にどのような挙動をするかではなく、属性の存在が必須(要求される)[REQUIRED]かどうかの情報を提供するものとします。

 属性既定値は以下のように記述します。


'#REQUIRED'

または

'#IMPLIED'

または

属性値

'#FIXED' 属性値

 属性定義上では、#REQUIREDの意味するところは、その属性に常に既定値がある状態を指し、#IMPLIEDは、既定値がないという条件を意味します。

 もし、#REQUIREDでも#IMPLIEDでもないケースがあるとしたら、指定した属性値を既定値として定義されているものとします。

 #FIXEDキーワードがある場合には、常に既定値が固定であるものとします。

 XMLプロセッサが既定値定義された列挙型の属性のない要素に直面した場合には、アプリケーションに既定値が定義された属性として渡さなければなりません。


◆妥当性制約 / 要求される属性値

もし、既定の定義が#REQUIREDであれば、その属性値は、属性リスト定義にあるタイプの要素全てが列挙されていなければならない。


◆妥当性制約 / 属性既定値が正規化される場合

既定値定義は、属性タイプの定義された制約があるものとし、それが属性の既定値になります。

・IDREFまたはENTITYというタイプが名前付き属性に使われる文字列であること
・IDREFSまたはENTITIESというタイプが名前付き属性に使われる文字列であること
・NMTOKENというタイプが名前付き属性に使われる文字列であること
・NMTOKENSというタイプが名前付き属性に使われる文字列であること
・列挙型('NOTATION'か'enumeration') が列挙された値と一致していること

 これはここで要求されたタイプの制約に限定されます(例えば値に解析されない実体を定義した名前があるとするとそれはENTITYというタイプの名前になります。)。


◆妥当性制約 / 固定の(#FIXED)属性値

もし属性が#FIXEDキーワードで定義された既定値を持つならば、属性のインスタンスは既定値と一致していなければなりません。

 これはここで要求されたタイプの制約に限定されます(例えば値に解析されない実体を定義した名前があるとするとそれはENTITYというタイプの名前になります)。

 属性リスト定義の例は以下の通りです。


<!ATTLIST termdef
    id    ID    #REQUIRED
    name    CDATA    #IMPLIED>
<!ATTLIST list
    type    (bullets|ordered|glossary) "ordered">
<!ATTLIST form
    method    CDATA    #FIXED "POST">

属性値の正規化

 属性値がアプリケーションに渡される前、妥当性検証される前にXMLプロセッサは、以下のアルゴリズムによって正規化されるか、アプリケーションに渡される値は前述同様のアルゴリズムに沿ったメソッドで処理生成されなければいけません。


1.全ての改行[CR][LF][CR/LF]は、前述の『行終端処理』で記述されたように1つの[LF](16進数表記では#xA)に置き換えた正規化を行わなければいけません。
2.カラ文字を含んだ値から正規化します。
3.属性値として正規化されていない文字列や実体参照、文字参照はそれぞれ、最初と最後に続く次のようになります
 ・文字参照は、正規化された文字の参照を付加
 ・実体参照は、実体の代替テキストにこのアルゴリズムの3項めを再帰的に適用
 ・ホワイトスペース文字(#x20, #xD, #xA, #x9)(意味既出)は、正規化された1つのスペース(#x20)に置き換える
 ・他の文字は正規化された文字を付加

 もし、属性タイプが(CDATAの場合はそのまま渡されますが)「CDATAでない」場合には、XMLプロセッサは先頭と終端のスペース(#x20)を取り除き、中間に連続したスペース(#x20)があれば、1つのスペース(#x20)に置き換えます。

 もし、属性値が正規化されていなければ


ホワイトスペース文字やその他のスペース(#x20)を持つ文字参照を含んでいる場合や正規化されていない値に[#xD]、[#xA]、[#x9]といった文字が含まれている場合の比較、
(参照されない)ホワイトスペースを含む正規化されていない値がある場合の比較
正規化された1つのスペース(#x20)に置き換える場合の比較
ホワイトスペースを含む代替テキストの実体参照を含む正規化されていない値を比較

をして、それぞれ再帰的に複数のホワイトスペースを正規化された1つのスペース(#x20)に置き換えます。

 読み込まれた定義されていない全ての属性が、CDATAで定義されていたとしたら、(他の制約ではエラーになるものが、この場合にはエラーではないので)非妥当性検証(妥当性不検証)プロセッサによって処理されるべきです。

 但し、定義が読み込まれていない実体の参照が含まれていたら属性値はエラーになるものとします。

 属性値正規化定義の例


<!ENTITY d "&#xD;">
<!ENTITY a "&#xA;">
<!ENTITY da "&#xD; ">

 以下の属性仕様について表すと

属性仕様
a="xyz"
a="&d;&d;A&a;&#x20;&a;B&da;"
a="&#xd;&#xd;A&#xa;&#xa;B&#xd;&#xa;"

 左の列は、「aという属性がNMTOKENSだった場合」右の列は、「aという属性がCDATAだった場合」を表しています。

a が NMTOKENSa が CDATA
x y z
#x20 #x20 x y z
A #x20 B
#x20 #x20 A #x20 #x20 #x20 B #x20 #x20
#xD #xD A #xA #xA B #xD #xA
#xD #xD A #xA #xA B #xD #xA

 例の最後は、「aという属性がNMTOKENSだった場合」というのは現実的ではない為?適した例とは言えませんが、仮にそうだったとしたら整形式と呼ぶことができます。

文法条件セクション

 文法条件セクションの定義は、文書タイプ宣言外部サブセットのDTD(document type declaration external subset)と外部実体参照の一部であり、この定義が適用される範囲にある有効なキーワードに基づいたDTDの物理的構造の内部または外部の形式です。

 実体参照の例は次の通りです。


<!ENTITY % draft 'INCLUDE' >
<!ENTITY % final 'IGNORE' >

<![%draft;[
<!ELEMENT book (comments*, title, body, supplements?)>
]]>
<![%final;[
<!ELEMENT book (title, body, supplements?)>
]]>


◆妥当性制約 / 正規の文法条件とPEネスト

もし、パラメータ実体参照の代替テキストにXML文法条件上、使われる"<!["、"["、"]]>"などが含まれていたら、それらすべては同一の代替テキストの中に含まれていなければならない。
つまり、ATTLISTやENTITYなどの宣言の開始や終了、CDATAでもこうした記号が使われるので代替テキスト中にいずれかだけが含まれているとエラーや混乱の元となるのでもし記述する必要があるのならばセットで記述しましょう。

 もし、XML文法条件セクションのキーワードが[INCLUDE]の場合には、文法条件セクションの内容は、DTDの一部として処理されなければいけません。

 逆にもし、XML文法条件セクションのキーワードが[IGNORE]の場合には、文法条件セクションの内容は、DTDの一部として処理されてはいけません。

 もし、より広義のXML文法条件セクションのキーワードが[IGNORE]の場合には、外部や内部の文法条件セクションは共に無視されなければいけません。

 この時、無視されたXML文法条件セクションは、本来のセクションの終わりを表す【]]>】が見つかるまでは、後に続いて存在するかもしれません。


[INCLUDE]/[IGNORE]といったキーワード
XML文法条件セクションの開始を表す"<!["やセクションの終わりを表す"]]>"

を全て無視して他の文字を解析しなければいけません。

 パラメータ実体参照で、このプロセスを認識させてはいけません。

 もし、XML文法条件セクションのキーワードがパラメータ実体参照である場合には、そのパラメータ実体は、それ以前にあった内部または外部のXML文法条件セクションに置き換えなければいけません(こうしたケースが生じる場合には現在のXML文法条件セクションのスコープ(有効範囲)から外れる事を考慮しておかなくてはいけません)。

構造の中身

 XML文書は、1つまたは複数の記憶装置(ハードディスクなどの記憶媒体)にあるかもしれません。

 この場合、文書にあるもの全てと文書実体や外部DTDサブセットを除く「実体名」によって識別される全ての実体は呼び出(コール)されるものとします。

 それぞれのXML文書は、1つの実体を持っていて、文書(ドキュメント)実体としてXML文書の開始位置情報や全ての文書を含めて呼ばれるかもしれないものとします。

 実体は解析される場合もあれば解析されない場合もあるものとします。

 解析された実体が代替テキストとして参照されるケースでは、その代替テキストは、XML文書を構成する重要な一部分であると認識されるものとします。

 解析されない実体の中身は、テキストかもしれないし、テキストではないかもしれないリソースで、それがもしテキストだったとしてもXMLではないかもしれません。

 こうした解析されない実体もXML表現として名前で識別されるものとします。

 XMLプロセッサは、こうした実体識別要求の為の実体表記はアプリケーションで受け取ることを可能にするものであるものとし、XMLでは解析されない実体の中身に対する制約はないものとします。

 実体参照で名前によって呼び出される解析された実体や名前によって呼び出される解析されない実体もまた[ENTITY]属性または[ENTITIES]属性の値として返されます。

 正規化された実体は、文書を含む内容を利用する為の実体です。

 この仕様では、正規化された実体は、曖昧な語句ではない時に実体と呼び、無条件で参照される事があるものとします。

 パラメータ実体は、DTDがなくても実体解析されるものとします。

 実体を利用する際のこれら2つの異なる参照形式は、前後関係などの状況によって区別して認識されるものとします。

 更に名前空間が異なるので、同名のパラメータ実体と正規化された実体のこれら2つは個別に扱う事ができるようになっています。

文字参照と実体参照

 文字参照は[ISO/IEC 10646]の文字セットによる文字仕様を参照するものとします。

 文字参照方法は以下の通りです。


'&#' '[0-9]+' ';'

または、

'&#x' '[0-9a-fA-F]+' ';'

※'+'は必須である事を表します。
※'x'は16進数表記(0~f)である事を表します。
※'x'がつかない場合は10進数表記である事を表します。


◆整形式文書制約

記述できる文字は、#x9 | #xA | #xD | [#x20-#xD7FF] | [#xE000-#xFFFD] | [#x10000-#x10FFFF]の範囲でなければいけません。

 もし文字参照が'&#x'で始まる場合、その後には数字[0-9]や文字[a-f][A-F]が続きますが、こうした文字コードの16進数表現におけるポイントについては[ISO/IEC 10646]で定められています。

 もし文字参照が'&#'で始まる場合、その後には数字[0-9]が続くというのは、文字コードの10進数表現におけるポイントです。

 実体参照とは、名前付けされる事によって一意に識別できる実体の参照を意味するものとします。

 解析された実体の一般的な参照には、[&]が[&amp;]であるようにアンパサンド/ampersand[&]とセミコロン[;]という2つの区切り文字(デリミタ)を使って表現するものとします。

 パラメータ実体参照には、パーセント/percent-sign[%]とセミコロン[;]という2つの区切り文字(デリミタ)を使うものとします。


◆整形式文書制約 / 実体定義

何らかのDTDのない文書とは、パラメータ実体参照のない内部DTDのみを持つ文書または、[standalone='yes']を宣言で指定した場合を指し、その為、外部サブセットやパラメータ実体のない実体参照の場合には実体参照の為に付与された実体参照名は、外部サブセットやパラメータ実体を含むものではないという実体定義と一致しなければいけません。
但し、整形式文書として[amp, lt, gt, apos, quot]といった実体のように定義の必要がないものを除きます。
正規化された実体の定義としては、属性リスト定義にある既定値として設定された値を優先して参照しなければいけません。

 実体定義が必要なパラメータ実体があった場合や外部サブセットの中でそのような文書があった場合でも、[standalone='yes']と宣言している場合に限ってその文書は整形式文書制約に沿ったものとしなければならないとするルール等、非妥当性検証プロセッサは解析を行う義務はありません。


◆妥当性制約 / 定義された実体

[standalone='no']で外部サブセットやパラメータ実体参照を伴う文書では、実体参照名が実体定義と一致していなければいけません。
妥当なXML文書としては、予め定義される実体として[amp, lt, gt, apos, quot]といった実体を定義すべきです。
パラメータ実体の定義としては、その予め定義された実体を参照しなければいけません。
正規化された実体参照としては、正規化された実体を直接参照または内部参照を伴う既定値を含む属性リスト定義を予め定義しなければいけません。


◆整形式文書制約 / 解析された実体

実体参照というのは、解析されない実体の名前を含んではいけません。
解析されない実体は[ENTITIE]や[ENTITIES]というタイプとして定義された属性値だけを参照するかもしれません。


◆整形式文書制約 / 再帰はありません

解析された実体は、直接的、間接的に関わらず自分自身を参照する(再帰)をしていはいけません。


◆整形式文書制約 / DTDについて

パラメータ実体参照はDTDの有効範囲の外に出てきてはいけません。
(パラメータ実体参照はDTDの有効範囲内でしか行う事ができません)

実体定義

 実体は以下のように定義するものとします。


<!ENTITY 実体名 [実体値]または[外部ID 'NDATA' 実体名]>

または、

<!ENTITY % [実体名] [実体値]または[外部ID]>

 実体参照による名前識別または、解析されない実体の場合には、[ENTITY]属性または[ENTITIES]属性の値の中にあるものとします。

 もし、同じ実体が1回以上定義されていた場合、最初に見つけた定義を有効とするものとします。

 この時、XMLプロセッサは、「実体が複数回定義されています」といった警告を出す事もあり得るものとします。

内部実体

 もし、実体定義が空の値だった場合には、定義された実体は、内部実体として呼ばれるものとします。

 これは物理的な記憶装置を分割しない事を意味し、実体の中身は定義の中で与えられるものとします。

 リテラル空文字による実体や文字参照の解析をした場合、代替テキストへの置き換えを要求される事もあり得るものとします。

 内部実体は解析された実体を指すものとし、例えば、以下のように定義するものとします。


<!ENTITY Pub-Status "This is a pre-release of the specification.">

外部実体

 もし、実体が内部にはない場合には、それは外部実体であるものとします。

 実体は以下のように定義するものとします。


SYSTEM [^"]*または[^']*

または、

PUBLIC ※ [^"]*または[^']*

※には、[#x20]または[#xD]、[#xA]、[a-zA-Z0-9]、[-'()+,./:=?;!*#@$_%]が入ります。

 また、解析されない外部実体の場合には以下のように定義します。


NDATA [外部実体名]

 もし、[NDATA]という宣言があった場合には、「解析される実体」に対して「解析されない実体」の定義であるものとします。


◆妥当性制約 / 記述定義

実体名は、記述定義で定義されたものと一致しなければいけません。

 システムリテラルは実体のシステム識別子として呼ばれるものとします。

 システムリテラルが意味するのは、実体の代替テキストを処理するXMLプロセッサにとって条件を満たした入力を間接参照する為の一部として[IETF RFC 3986]で定義されているURI参照の為に変換されるものです。

 システム識別子の一部である[#]で始まる文字などを使った場合、フラグ識別におけるエラーがあり得るものとします。

 XML特有のDTDで定義された特別な要素タイプや特有のアプリケーション仕様として定義された処理命令などXML特有の仕様の「範囲外」の情報については除外するものとします。

 範囲外とは、関連するURIが指し示す場所が、実体定義されていない内容が含まれるリソースの場合を指すものとします。

 定義通り解析されている場所である開始を表す[<]などは外部実体として定義されているものとします。

 このように外部DTDサブセットに含まれた実体としてURIが文書実体や他の外部実体に関連している事もあり得ます。

 URIで示された場所の検索試行中に例えば、実体リゾルバ(解決)などXMLパーサーレベルや例えばHTTP経由の[Location]ヘッダなどのプロトコルレベルでリダイレクトされる事もあり得ます。

 このようなXML仕様を超えたところからの付加的な情報であるリソースのURIを基にした情報は、常に閲覧可能な状態でなければいけません。

 言い換えれば、リソースを指し示すURIにリダイレクトが必要な場合には、必ず全てリダイレクト先に訂正したURIが検索されなければいけないという事です。

 URIリソースを指し示すXMLの文字列であるシステム識別子は、[IETF RFC 3986]で指し示すような文字を含んでいる事もあり得るものとし、このシステム識別子は、URIでリソースを検索する前にエスケープしなければならないものとします。

 エスケープされた文字は、往々にしてXMLで記述する事ができない管理文字である[#x0]から[#x1F]までの範囲と[#x7F]やスペースを表す[#x20]や区切り文字である'<'を表す[#x3C]や'>'を表す[#x3E]、シングルクォーテーション(')を表す[#x22]、中カッコの開始'{'を表す[#x7B]や終了'}'を表す[#x7D]や縦棒'|'を表す[#x7C]、バックスラッシュを表す[#x5C]、 '^'を表す[#x5E]と'`'を表す[#x60]など[#x7F]より上の範囲です。

 エスケープした後は常に元に戻す処理(reversible process)は行わないものとし、どうしても必要である場合や一連の処理が遅くなってしまうなどのケースのみ元に戻す処理が実行されなければいけません。

 特殊なケースとはいえ、URIリダイレクションの変換処理やソフトウェアコンポーネントの間接的な処理結果だったとしてもエスケープされるべきです。

 エスケープされる際には以下の実行がなされなければいけないものとします。


1.エスケープされたそれぞれの文字は、1バイト以上のUTF-8 [Unicode3]表現にする

2.結果のバイトはURIエスケープメカニズムによってエスケープする
  ([%HH]と変換されたとすると[HH]は16進数バイト値表現です)

3.元の文字は、文字シーケンスの結果として置き換える

 システム識別子が付加される場合には、外部識別子がパブリック識別子に含まれている事があり得るものとします。

 XMLプロセッサは、代替URI参照の生成をするといったこの仕様範囲外の付加的な情報と同じようにパブリック識別子とシステム識別子を組み合わせる事もあり得ます。

 もし、XMLプロセッサが、そうしなかった場合には、システムリテラルとして特化されたURI参照を利用しなければいけません。

 それ以前に、パブリック識別子に含まれる全てのホワイトスペースは1つの単独のスペース[#x20]に置き換える正規化をし、先頭と終端のホワイトスペースを取り除かなければいけません。

 外部参照定義の例は、以下の通りです。


<!ENTITY open-hatch
    SYSTEM "http://www.textuality.com/boilerplate/OpenHatch.xml">

<!ENTITY open-hatch
    PUBLIC "-//Textuality//TEXT Standard open-hatch boilerplate//EN"
    "http://www.textuality.com/boilerplate/OpenHatch.xml">

<!ENTITY hatch-pic
    SYSTEM "../grafix/OpenHatch.gif" NDATA gif >

解析された実体

 外部解析された実体はテキストで始まる文字列であるべきです。

テキスト定義

 テキスト定義は下記の通りで


<?xml [バージョン情報] [エンコード方式]?>

 テキスト定義の例は下記の通りです。


<?xml encoding='utf-8'?>

<?xml version="1.0" encoding='euc-jp'?>

 テキスト定義は一語一語定義されなければならず、解析された実体があるから参照するというものではありません。

 テキスト定義は外部解析された実体の開始位置以外に記述してはいけません。

 外部解析された実体によるテキスト定義は、代替テキストの一部として解釈されるわけではありません。

整形式文書として解析された実体

 文書実体は、記された文書と一致したものであれば、整形式文書であるという事ができます。

 外部で一般的に解析された実体は、


<?xml encoding='utf-8'?>

文字データまたは、要素か参照、CDATA、PI、コメントと文字データ(この時文字データはオプション)

のように記されたものと一致する場合において整形式であるという事ができます。

 また、全ての外部パラメータ実体は、定義される事によって整形式とされるものとします。

 文書の中で直接的、間接的に参照される実体が解析された時には、整形式という事ができます。

 内部的に一般的に解析された実体というのは、もし代替テキストが文書中に記されたものと一致すれば整形式ということができます。

 全ての内部パラメータ実体は、定義される事によって整形式とされるものとします。

 正規化された実体の整形式における結論は、厳密にネストされたXML文書中の構成が論理的、物理的である事です。

実体における文字エンコード方式
URLエンコード/URLデコード
文字コードと改行コード

 外部解析された実体は、XML文書のエンコード方式とは異なるものかもしれません。

 全てのXMLプロセッサは、UTF-8とUTF-16のエンコード方式を使ったどちらの実体も解読できなければいけません。

 どんなにUTF-8とUTF-16のエンコード方式やラベルが似ていたとしてもこの仕様上でのUTF-8とUTF-16は他のラベルを伴った文字エンコード方式を適用するものではないからです。

 実体のUTF-16によるエンコードは、[ISO/IEC 10646:2000]で定めのある[ANNEX H]※で表現される[Byte Order Mark]で始まるかもしれません。

 ※ANNEX H[ANNEX HはDSL規格というADSLと同類の通信規格のひとつであるG.992.1(G.dmt)という規格の付帯規格で、同規格をベースにして上下対称速度のSDSLを行なうための仕様でこれによって実現できるSDSLをSSDSL(Synchronized Symmetric DSL)と呼ぶこともある]

 これはエンコードの署名であってXML文書のマークアップでも文字データでもありません。

 XMLプロセッサは、UTF-8やUTF-16でエンコードされた文書のこれら文字の相違を吸収して利用しなければいけません。

 とはいえ、XMLプロセッサは、UTF-8やUTF-16でエンコードされた実体の解読要求がある事もあり、世界中で使われているエンコード方式を理解できますし、それらのエンコード方式での実体解読がXMLプロセッサに要求される事もあり得ます。

 MIMEメールヘッダのように外部文字の文字エンコード方式の情報が欠如している場合でもUTF-8やUTF-16以外のエンコード方式で保存された実体も解析し、エンコード方式に内包するテキスト定義で定められた文字で始まるテキストにしなければいけません。

 エンコード方式定義では、UTF-8やUTF-16、[ISO-10646-UCS-2]そして[ISO-10646-UCS-4]の値は、[Unicode]/[ISO]/[IEC 10646]など様々なエンコード方式を利用するべきです。

 [ISO-8859-1]、[ISO-8859-2]...[ISO-8859-n]([n]には番号が入ります)は、[ISO 8859]として利用されるべきです。

 そして[ISO-2022-JP]、[Shift_JIS]そして[EUC-JP]は、[JIS X-0208-1997]の形式で様々なエンコード方式が利用されるべきです。

 それらの文字セットはIANA(Internet Assigned Numbers Authority/インターネットに関連する番号を管理する世界的な国際組織)によって [IANA-CHARSETS]として登録され勧告されているもので、その他のものも含め登録名称を利用する際に参照されます。

 他のエンコード方式は名前の先頭に"x-"という接頭語(プリフィクス/prefix)を付けて利用されるべきです。

 XMLプロセッサは、英文字(アルファベット)の大文字と小文字を区別しない方法でエンコード方式と文字を一致させるべきです。

 そして他のエンコード方式としてそれを[unknown]という名前と扱いでIANAに登録されるエンコード方式としてのIANA登録名は国際的に解釈されるべきです。(もちろんプロセッサがIANAに登録されているエンコード方式を全てサポートする事を求めているわけではありません)

 HTTPやMIMEのような外部の転送プロトコルによって提供された情報が欠如しているものについては、そのエンコード方式で名付けられた他のエンコード方式においてXMLプロセッサに示されるエンコーディング定義を含む実体も、また、[Byte Order Mark]でもなく、UTF-8の他のエンコード方式を使ったエンコード定義でもないもので始まる実体も致命的エラー[fatal error]です。

 ASCIIはUTF-8のサブセットで通常ASCIIでは実体はエンコード定義を厳密に必要としていません。

 外部実体で始まる他のものもテキスト定義上、致命的エラーです。

 つまり、XMLプロセッサが、処理できないエンコード方式を使った実体に遭遇すればそれは、致命的エラーということです。

 もし、実体の中身が確かに既定、またはエンコード定義、もしくは高レベルのプロトコル経由でエンコードされているとしても、そのエンコード方式でエンコードした中に妥当でないバイトの並びがあれば、それは致命的エラーということです。

 特にそれが高レベルプロトコルによるものであったとしても実体の中身がエンコード定義と一致していなかったり、その内容がUTF-8やUTF-16に沿っていなければ、それもまた致命的エラーということです。

XMLプロセッサの実体と実体参照の扱い

 以下のテーブルは、文字参照、実体参照、解析されない実体があるかもしれない点、そうした参照がXMLプロセッサの背後で求められた場合をまとめたものです。

Entity TypeCharacter
ParameterInternal GeneralExternal Parsed GeneralUnparsed
Reference in Content Not recognized Included Included if validating Forbidden Included
Reference in Attribute Value Not recognized Included in literal Forbidden Forbidden Included
Occurs as Attribute Value Not recognized Forbidden Forbidden Notify Not recognized
Reference in EntityValue Included in literal Bypassed Bypassed Error Included
Reference in DTD Included as PE Forbidden Forbidden Forbidden Forbidden


◆内容の参照とは

開始タグの後で且つ終了タグの前(開始タグと終了タグで挟まれた)内容であり、内容の終端ではない部分の参照。


◆属性値内の参照とは

開始タグにある属性の値や属性定義の既定値の中での参照で且つ属性値の終端ではない部分の参照。


◆属性値と言えば

ENTITYというタイプで定義されている属性の値、ENTITIESというタイプで定義される属性の値の中のスペースで区切られたトークンそれぞれの事で名前付け規則に沿ったもの。


◆実体における参照とは

実体の定義にあってパラメータや内部実体のリテラル実体値であって実体値の終端ではないものの中身の参照。


◆DTDにおける参照とは

DTDの内部サブセットまたは外部サブセット内の参照の事ですが、実体値、属性値、PI、コメント、システムリテラル、PubIDリテラルや文法条件セクションが無視された内容における参照。

認識されないケース

 DTDの外では[%]文字は特別な意味を持ちません。

 このようにDTDの中で参照されるパラメータ実体は、マークアップとして認識されません。

 似たケースとして解析されない実体の名前は、属性定義に沿った値でない限り、認識されません。

含まれるというケース

 代替テキストが文中のある部分のある場所の参照が認識されたような場合、実体自身が参照された場所で検索や解析において代替テキストが含まれている場合を指すものとします。

 代替テキストには、文字データとパラメータ実体を除くマークアップが含まれているかもしれませんが、それは普通に認識されなければいけません。

 例えば、[AT&amp;T]とあった場合には、[AT&T]であってアンパサンド[&]が実体参照の区切り文字として認識されないようにするという事です。

 文字参照は、その指し示す文字が参照された場所で解析された時、含まれているという事ができます。

もし妥当なら含まれるというケース

 XMLプロセッサは、妥当な文書の中で解析された実体の参照が認識された時、実体と実体参照だけでなく代替テキストも含まなければいけません。

 もし、実体が外部にあってXMLプロセッサがXML文書としての妥当性検証で失敗したとしてもXMLプロセッサは、実は実体の代替テキストを必要としていないというケースもあるかもしれません。

 もし、非妥当性検証プロセッサが代替テキストを含んでいない場合は、実体を解読しないまでもその実体の存在が認識できるようにアプリケーションに知らせなければいけません。

 この規則は、XML(やHTML)のスーパーセットであるSGMLとXML実体メカニズムによって自動的に認識されるという点に基づいていて、元来、文書作成モジュール化のサポートという形のものであるこのメカニズムは、XML文書という特有の文書を閲覧する為にこうした妥当性が必要なのであって他のアプリケーションにとって妥当である必要はありません。

 ブラウザは、例えば、実体参照の外部解析があった場合、画面上で視覚的にその実体の存在と検索を指し示して情報を提供するという選択をするかもしれません。

禁じられているケース

 次のようなケースは禁じられていて、そうした構成は致命的エラーとなります。


・実体定義にある実体値以外の解析されない実体の参照

・実体値や属性値以外のDTDの中で参照される文字や正規化された実体

・属性値の中で外部実体を参照すること

リテラル文字が含まれているというケース

 属性値の中に実体参照があった時やリテラル実体値の中にパラメータ実体参照があった時は、それがシングルクォーテーションやダブルクォーテーションで括られたもの以外は、認識された参照場所のある文書のその部分を代替テキストとして解析しなければいけません。

 シングルクォーテーションやダブルクォーテーションで括られた文字は、通常の文字としてのデータとして扱わなければならず、リテラル文字の終端として扱っていはいけません。

 例えば以下の前者のケースは整形式であると言えますし、後者はNGです。


◆整形式であるケース

<!ENTITY % YN '"Yes"'>

<!ENTITY WhatHeSaid "He said %YN;" >


◆整形式といえないケース

<!ENTITY EndAttr "27'">

<element attribute='a-&EndAttr;>

※整形式と言えないケースでは、いずれもシングルクォーテーションが欠落しています。

報告が必要なケース

 ENTITYやENTITIESというタイプで定義されている属性の値の中にあるトークンのように解析されない実体名があった時、妥当性検証プロセッサは、実体と実体の表記法の両方のパブリック識別子とその仕組みをアプリケーションに渡さなければいけません。

迂回が必要なケース

 正規化された実体が実体定義の属性値として参照される時には、実体参照をせず、迂回して一般的に知られる実体として認識しなければいけません。

PEとして含まれるケース

 外部解析された実体を伴うパラメータ実体は、妥当である場合に限り必要です。

 パラメータ実体が参照される時は、DTDで認識される、含まれている、という状態でその実体の代替テキストは、展開して先頭から続けてスペース文字[#x20]埋めして左詰めで調整しなければいけません。

 これが意図するところは、DTDの文法に沿ったトークンの必須番号を含むパラメータ実体の代替テキストの制約という事です。

 ここで言っている内容は『リテラルが含まれるというケース』にもあるように実体値の中にあるパラメータ実体参照に適用してはいけません。

エラーについて

 実体定義にある実体値の中にある解析されない実体の参照はエラーです。

実体代替テキストの構成方法

 実体の扱い方における議論の中で、2つの有力な識別する実体の形式があります。

 内部実体において、実体定義で現に行われている終端でない実体値であるそのリテラル実体値は、クォーテーションで括られるものとします。

 外部実体において、リテラル実体値は、実体の中に含まれている正確なテキストであるものとします。

 内部実体において、代替テキストは、実体の内容を表すものであるものとし、その後、文字参照やパラメータ実体参照で置換されるものとします。

 外部実体において、代替テキストは、実体の内容を表すものであるものとし、その後、テキストは、文字参照やパラメータ実体参照の代替テキストがなく、その必要があればホワイトスペース処理など余分なものを取り去るものとします。

 実体定義で定義されているリテラル実体値は、文字やパラメータ実体、正規化された実体の参照かもしれません。

 このような参照は、リテラル実体値の中に全て含まれていなければいけません。

 現行の代替テキストは表現上、代替テキストが含まれている(リテラルの中に含まれているものも含む)リテラル実体値の中で参照される文字がある場所でパラメータ実体が参照された代替テキストに含まれていなければいけませんし、文字参照に含まれていなければいけませんが、正規化された実体参照は、展開せずに左詰め処理しなければいけません。

 例えば次のケースでは、


<!ENTITY pub  "webzoit" >

<!ENTITY rights "All rights reserved" >

<!ENTITY site "webzodayo,&#xA9; 2004 %pub;. &rights;" >

とした場合、


webzodayo
© 2004 webzoit. All rights reserved

のように表示されます。

 一般の実体参照での"&rights;"は、文書内容や属性値にある"&site;"(の中身site)を参照して展開するものとします。

 これらの単純なルールは、複雑な相互作用を含んでいるかもしれません。難しい例についての詳細は、実体参照と文字参照拡張について(W3C英文)

定義済み実体

 予め定義されている実体には以下のようなものがあります。


<!ENTITY lt     "&#38;#60;">
<!ENTITY gt     "&#62;">
<!ENTITY amp    "&#38;#38;">
<!ENTITY apos   "&#39;">
<!ENTITY quot   "&#34;">

 実体参照と文字参照は、左側ブラケット"["やアンパサンド[&]やその他の区切り文字などがエスケープされているかもしれません。

 上記に挙げたような(lt、gt、amp、apos、quot)正規化された実体のセットは、この目的のための仕様です。

 数で表す文字参照は、認識された実体が正確に記述されたものであれば、文字データとして扱われなければいけません。

 だから[<]である[&#60;]と[&]である[&#38;]という数で表す文字参照は、文字として記述された時に[<][&]をエスケープする為に使われるかもしれません。

 全てのXMLプロセッサは、定義されているされていないに関わらず、これらの実体を認識しなければいけません。

 様々な環境で全体として正しい挙動をするという観点から妥当なXML文書は、これらの実体を利用する前に前述の実体のように定義すべきです。

 もし、[lt]や[amp]が定義された実体なら、代替テキストが、これらの実体それぞれの文字の参照を定義少なくともsignやアンパサンド[&]はエスケープされた状態であるという内部実体として定義されなければならず、これにより二重のエスケープは、整形された結果として生成された参照の実体を要求(REQUIRED)される事になります。

 もし[gt]、[apos]や[quot]が定義されていたら、代替テキストが単独の文字としてエスケープされているか、その文字が文字参照であるか、二重にエスケープされている影響のない安全な内部実体として定義されなければいけません。

表記定義

 表記は、解析されないフォーマットや属性表記を受けた要素のフォーマットや解析指示がアドレス指定するアプリケーションを名前によって識別するものとします。

 表記定義は、表記による名前の提供によって、実体や属性リスト定義や属性仕様上にある定義や仕様の参照利用や、XMLプロセッサやクライアントアプリケーションが、表記が与えられたデータの解析機能を持つヘルパーアプリケーションの位置を見つける事を可能にします。

 表記定義は、次のように記述します。


[NOTATION定義方法]
<!NOTATION [名称] [外部ID]または[パブリックID]>

[パブリックID]
PUBLIC [#x20] | [#xD] | [#xA] | [a-zA-Z0-9] | [-'()+,./:=?;!*#@$_%]

 例えば、<!ENTITY mylt "<">という表記のように単独の[<]が正規化された実体の定義で認められている実体だからと言って、整形式エラーの原因になる実体の参照となる可能性が高いので回避する事を強くアドバイスします。

文書実体

 ドキュメント実体は、XMLプロセッサに実体ツリー(階層構造)のルートと開始位置を提供するものとします。

 この仕様は、XMLプロセッサによって場所が特定されたドキュメント実体をどのように扱うかの仕様ではありません。

 他の実体でドキュメント実体が名前を持っておらず、すべてにおいて識別なしで解析入力ストリームに現れるかもしれないという事とは別であるという意味です。

一致

妥当性検証プロセッサと非妥当性検証プロセッサ

 XMLプロセッサにおける一致は、妥当性検証プロセッサと非妥当性検証プロセッサの2つのクラスからなっています。

 妥当性検証プロセッサと非妥当性検証プロセッサは、文書実体と解析された実体が読み込まれた文書がXML仕様上の整形式制約上の違反を報告しなければいけません。

 妥当性検証プロセッサは、ユーザーオプションでDTD定義内の制約違反やこの仕様上で与えられる妥当性制約に一致する失敗を報告しなければいけません。

 これを遂行するために妥当性検証プロセッサは、DTD全てを読み込んで解析し、文書中のすべての外部解析された実体参照をしなければいけません。

 非妥当性検証プロセッサは、整形式である為の内部DTDサブセット全てを含めて要求された文書実体に限定してチェックしなければいけません。

 妥当性の文書チェック要求がない間に、内部DTDサブセットとパラメータ実体を読み込み、読み込まれない一番最初のパラメータ実体を認識して定義を解析する事が求められます。

 どういうことかというと、通常の属性値や内部実体の代替テキストに含まれる値や属性の既定値として渡される値といったこれらの定義情報を利用しなければいけないという事です。

 但し、[standalone='yes']である場合を除きます。

 [standalone='yes']である場合は、実体定義や属性リスト定義が読み込んでいないパラメータ実体の参照の後に見つけた実体定義や属性リスト定義を解析してはいけません。

 ただ、その実体は上書きされるかもしれないのでその時は[standalone='yes']である場合は、XMLプロセッサは、これらの定義を解析しなければいけません。

 非妥当性検証プロセッサによる文書妥当性検証の解析である場合は、アプリケーションは一致する情報を提供しないかもしれません。

 例えば、文書中で一意のいくつかの要求では、同じIDや同じ名前を持つ要素や表記の重複した定義等々が2つ以上含まれるというケースに遭遇する事は(一意なので)ありません。

 こうしたケースにおいて、このようなアプリケーションが定義しない情報を報告する機能を持つのはパーサーです。

XMLプロセッサの利用

 妥当性検証プロセッサの機能は予想以上に高機能です。

 文書全体を読み込む事もさることながら、文書の断片を解釈して読み込み、全ての整形式制約と制約違反を報告します。

 非妥当性検証プロセッサに求められるものはそこまでではありません。

 非妥当性検証プロセッサでは、文書実体以外の文書内の一部を読み込んだりする必要はありません。

 この妥当性検証プロセッサと非妥当性検証プロセッサという2つがもたらす効果は、XMLプロセッサを利用するユーザーにとってとても重要なことかもしれません。


・確実な整形式制約エラー、特に外部実体を読み込み要求がある場合などに、非妥当性検証プロセッサではエラーを見つけられないかもしれません。
 例えば、『XMLプロセッサによる実体と参照の扱いについて』で記述されているように属性定義や実体解析、再帰しないケースといった制約がある場合も含まれます。

・XMLプロセッサがパラメータや外部実体を読み込むかどうかによってXMLプロセッサからアプリケーションに渡される情報が変化するかもしれません。
 例えば、非妥当性検証プロセッサは、属性値や内部実体の代替テキストや与えられた属性の既定値の正規化において、外部パラメータ実体やパラメータ実体のその場合には読み込むべきでない定義を読み込んでしまって失敗するかもしれません。

 様々な環境で全体として正しい挙動がなされるという観点からXMLプロセッサの違いによる最大の信頼性は、2つのプロセッサの使い分けにあり、非妥当性検証プロセッサを使ったアプリケーションでは、このようなプロセッサの要求しない挙動に頼るべきではありません。

 属性既定値の定義や外部実体の仕様上にあるものや内部実体にあるものも含めたDTDが関係しない妥当性検証には妥当性検証プロセッサを利用するべきです。

明記

 形式的なXMLの文法は、単純明快なバッカス・ナウア記法(Extended Backus-Naur Form (EBNF))に基づいています。

 文法定義のそれぞれの規則は、バッカス・ナウア記法の象徴的な部分です。

ホーム前へ次へ