本家「@IT」にはない内容をエンジニアライフで技術紹介するコラム。広く議論する場になることを目指します。

第040回_prolog_XMLDecl_VersionInfo

»
前回、XML文書(document)とXMLパーサの種類について説明しました。今回から生成規則を辿りつつそれぞれの構文の意味について解説・検討していきたいと思います。
documentの構文は、
 document ::= (prolog docElement Misc*)
ですから次はprologについて解説します。

prolog

prologの構文は、
 prolog ::= XMLDecl Misc* ( doctypedecl Misc* )?
ですから、
XMLDecl:XML宣言
Misc:任意のコメントと処理命令とホワイトスペースの集合
doctypedecl:任意のDOCTYPE宣言
から成ります。

ただし、前回XMLプロセッサの要件で述べたように、
XML1.1のプロセッサはXML1.0の文書も処理できるので、
結局、
 XML1.0の構文 prolog ::= XMLDecl? Misc* (doctypedecl Misc*)?
を認識して処理できなければいけません。

1.0と1.1の構文の違いはXMLDeclが省略できるかだけですから、
実装する構文としては、
 EbnfPrologNode prolog ::= XMLDecl? Misc* (doctypedecl Misc*)?
とすることになります。

これらは、XML文書の文書要素が示す内容より前に現れるのでプロローグと呼びます。

W3Cの勧告のプロローグの説明は次のようになっています。
「2.8 プロローグと文書型宣言」
----W3C勧告----
[Definition: XML 1.1 documents must begin with an XML declaration which specifies the version of XML being used.] For example, the following is a complete XML 1.1 document, well-formed but not valid:

 <?xml version="1.1"?>
 <greeting>Hello, world!</greeting>

but the following is an XML 1.0 document because it does not have an XML declaration:

 <greeting>Hello, world!</greeting>

----W3C勧告----
----日本語訳----
[定義: XML1.1の文書は、使われるXMLのバージョンを指定するXML宣言で始まらなければならない。] 例えば、整形式であるが、妥当ではない、完全なXML1.1の文書は次のようになる。

 <?xml version="1.1"?>
 <greeting>Hello, world!</greeting>

しかし、次の例は、XML宣言を持っていないのでXML1.0の文書である。

 <greeting>Hello, world!</greeting>

----日本語訳----

以上の解説からVisitorのvisit(EbnfPrologNode n)の整理は次のようにできます。
 XMLDecl?を処理した後に、XMLDeclが示すバージョンを確認し、もし未宣言であれば自動的にバージョン情報に1.0を設定する

■visit(EbnfPrologNode n)を実装しない工夫
結局のところ
 バージョン値のデフォルト値が1.0でもしXML宣言があれば1.1にする
と処理して良いので、visit(EbnfPrologNode n)を実装する必要はありません。

XMLDecl

XMLDeclはXML宣言です。
その構文は、
 XMLDecl ::= '<?xml' VersionInfo EncodingDecl? SDDecl? S? '?>'
ですから、
VersionInfo:XMLのバージョン
EncodingDecl:エンコーディング宣言(オプション)
SDDecl:スタンドアロン文書宣言(オプション)
を定義します。

EbnfXMLDeclNodeはVistor上で特に意味のある処理をしません。

VersionInfo

VersionInfoはXMLのバージョンです。構文は、
 VersionInfo ::= S 'version' Eq ("'" VersionNum "'" | '"' VersionNum '"')
 Eq ::= S? '=' S?
 VersionNum ::= '1.1'
ですから、
version:WORD ('version')
Eq:両端にホワイスペースを含むSYMBOL ('=')
1.1:LITERAL ('1.1')
から成ります。

VersionInfoはXMLDeclだけでなく、外部解析対象実体のTextDeclにも書くことができます。W3Cの勧告では次のように説明があります。

----W3C勧告----
4.3.4 Version Information in Entities

Each entity, including the document entity, can be separately declared as XML 1.0 or XML 1.1. The version declaration appearing in the document entity determines the version of the document as a whole. An XML 1.1 document may invoke XML 1.0 external entities, so that otherwise duplicated versions of external entities, particularly DTD external subsets, need not be maintained. However, in such a case the rules of XML 1.1 are applied to the entire document.

If an entity (including the document entity) is not labeled with a version number, it is treated as if labeled as version 1.0.
----W3C勧告----
----日本語訳----
4.3.4 実体のバージョン情報

文書実体を含む各実体は、XML1.0かXML1.1を各々に宣言することができる。文書実体の中で出現するバージョン宣言は全体の文書のバージョンを決定する。XML1.1の文書がXML1.0の外部実体を呼び出しても良い。したがって、バージョンだけが異なる外部実体、特にDTD外部サブセットを用意する必要はない。しかしながら、XML1.1の文書実体で外部実体が1.0の場合でも文書の全体は1.1のルールを適用する。

もし文書実体を含めた実体がバージョン番号を持たない場合、バージョン1.0として扱われる。
----日本語訳----

仕様を整理すると次のようになります。

■XMLDeclのバージョン情報の取り扱い
 1.0か1.1が指定できる。
 もし未定義なら1.0として扱う。

■TextDeclのバージョン情報の取り扱い
記述することはできるが結果的にXML文書のバージョン情報に従って処理するので無視してかまわない。

この仕様はVersionNumの構文は1.1しか許容できないのですから、XML1.1のVersionNumの構文と合致しません。

ただし、前回XMLプロセッサの要件で述べたように、XML1.1のプロセッサはXML1.0の文書も処理できるという適合性を考慮に入れれば納得できます。
結局、実装する構文は
 VersionInfo ::= S 'version' Eq LITERAL ('1.0') | LITERAL ('1.1')
とすることになります。
#
# Note: XML1.0のVersionNumの構文は VersionNum ::= ([a-zA-Z0-9_.:] | '-')+
# ですが実質1.0または1.1しか許容しませんので上記の処理で問題ないでしょう。
#

■バージョン値を設定するための工夫
EbnfVersionInfoNode全体でバージョン値設定処理を行うのは面倒です。
そこで構文を
 VersionInfo ::= S 'version' Eq Literal ('1.0') | Ver1_1
 Ver1_1 ::= LITERAL ('1.1')
に変更します。

Visitor側での処理は
Version情報の文字列のデフォルトは1.0とする
Version情報が1.0の場合は何もしない
Visitor#visit(EbnfVer1_1Node n)の処理でm_resultがOKの場合はVersion情報の文字列として1.1を設定する
とします。
Comment(0)

コメント

コメントを投稿する