f

アーカイブ

2015-12-29

XML宣言の正しい書き方:<?xml version="1.0" encoding="UTF-8"?>

XML文書を作成するとき、ファイルの1行目に以下のようなXML宣言(XMLDecl)を記述することが推奨されている。

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

しかし、ここで以下の5の疑問が生じる。

  1. そもそもこのXML宣言は必要なのか?
  2. versionの値は何を使うべきか?
  3. encodingの値は何を使うべきか?
  4. standalone属性は省略して問題ないのか?
  5. XML宣言の終端である?>の直前に空白を入れるべきか?

これらの疑問を解消し、最も推奨される正しいXML宣言を書き方に関する根拠を得るためにXML 1.0(第五版)の勧告文書を調べた。

結論からいうと、XML文書には冒頭に書いたものと同じ以下の内容をファイルの1行目に書くべきだ。

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

XML宣言は書くべきだし、versionとencodingの値もこの通りにし、standalone属性は省略すべきだ。

以下では勧告文書を調べて得られた結論と根拠を示す。

XML宣言(XMLDecl)の定義

XML 1.0(第五版)の勧告文書により、XML文書とは以下の3条件を満たす(整形式である)文書である。

  1. document生成規則にマッチ。
  2. 全ての整形式性制約を満たす。
  3. 文書中で参照される解析対象実体が整形式である。

参照元:2.1 整形式のXML文書 Well-Formed XML Documents

ここで、2.と3.に登場した[整形式性制約]と[解析対象実体]はXML宣言と関係ないので説明は省略し、document生成規則について説明する。

document生成規則とは、以下のバッカス・ナウア記法(EBNF:Extended Backus-Naur Form)で定義される。なお、EBNF自体も6 仕様書の記法 Notationで定義されている。

document ::= ( prolog element Misc* )

これが意味することは以下である。

  • 要素の前にプロローグ(prolog)が存在。
  • 一つ以上の要素(element)を含む。
  • ルート要素が一つだけ存在すること。

elementとMiscの説明はXML宣言と関係ないので省略する。

プロローグ(prolog)とは、ドキュメントの開始タグつまりルート要素の前に存在する情報を指す。プロローグには、文字エンコーディングなどドキュメント全体に適用される情報が含まれる。XML宣言はプロローグに含まれる。

プロローグは以下で定義される(2.8 プロローグと文書型宣言 Prolog and Document Type Declaration)。

prolog ::= XMLDecl? Misc* ( doctypedecl Misc* )?
XMLDecl ::= '<?xml' VersionInfo EncodingDecl? SDDecl? S? '?>'

XML宣言とは上記のプロローグの定義で登場するXMLDeclのことである。XML宣言という言葉については以下の定義がある。

[Definition: XML文書は、使われるXMLのバージョンを指定するXML宣言から始まる事が望ましい(SHOULD)。 ]

[Definition: XML documents SHOULD begin with an XML declaration which specifies the version of XML being used.]

参照元: 2.8 プロローグと文書型宣言 Prolog and Document Type Declaration - Extensible Markup Language (XML) 1.0 (第五版)

ここでの定義から、「XML宣言とは、XML文書に使われるXMLのバージョンを指定する宣言のこと」と解釈できる。

prologの定義でXMLDecl?とあるように、XMLDeclは0回以上存在すればよいので必須ではない。しかし、上記でXML宣言の記述が推奨されているため、書くべきである。

XML宣言(XMLDecl)は上記定義より以下の部品から構成されている。

'<?xml'VersionInfoEncodingDecl?SDDecl?S?'?>'

なお、ここでEncodingDeclSDDeclSは末尾に?が付いているので必須ではない。したがって、最小限のXML宣言は以下のようになる。

<?xml version="1.0"?>

以下ではこれらのXML宣言の各部品について説明していく。

'<?xml''?>'S?

まず、説明が簡単な'<?xml''?>'だ。これらはそのまま文字列として記述する。

次に、S?だ。

Sはホワイトスペースのことであり、一つ以上のスペース文字(#x20)、キャリッジリターン(#xD)、ラインフィード(#xA)、タブ(#x9)から構成される。2.3 一般的な構文構成子 Common Syntactic Constructsで以下の内容で定義される。

S ::= ( #x20 | #x9 | #xD | #xA )+

XML宣言ではS?と表記されているため、'?>'の直前に配置されるホワイトスペースはあってもなくてもよい。

VersionInfo

VersionInfoはXMLDeclのすぐ下で定義されている。

VersionInfo ::= S 'version' Eq ( "'" VersionNum "'" | '"' VersionNum '"' )
Eq ::= S? '=' S?
VersionNum ::= '1.' [0-9]+

この定義により、version="1.0"version = '1.012'のような書き方が許可されている。

VersionNum生成規則は'1.x'の形であればあらゆるバージョン番号にマッチするが、XML 1.0文書が'1.0'以外のバージョン番号を指定する事は望ましくない(should not)。

Even though the VersionNum production matches any version number of the form '1.x', XML 1.0 documents should not specify a version number other than '1.0'.

参照元:2.8 プロローグと文書型宣言 Prolog and Document Type Declaration - Extensible Markup Language (XML) 1.0 (第五版)

また、現在XMLはXML 1.0とXML 1.1の2種類が存在する。しかし、以下の4点の理由からXMLのバージョンには"1.0"を選択するべきだ。

  1. XML 1.1固有の機能が必要とされる場面が極めて少ない
  2. XML 1.1の勧告でプログラムはXML 1.0を生成することが望ましいと記述されている
  3. XML 1.1はXML 1.0へ基本的に後方互換性がある
  4. XML 1.1の機能の一部はXML 1.0第五版にバックポートされている

参照元:My Future Sight for Past: XMLのバージョンに1.1ではなく1.0を使うべき4の理由

EncodingDecl?

EncodingDeclはエンコーディング宣言(EncodingDecl)である。エンコーディング宣言の役割は以下で示されている。

XMLのエンコーディング宣言は、それぞれの実体の内部ラベルとして機能し、どの文字エンコーディングが使われているかを示す。

The XML encoding declaration functions as an internal label on each entity, indicating which character encoding is in use.

参照元:F 文字エンコーディングの自動検知(非規範的) Autodetection of Character Encodings (Non-Normative)

このことから、「エンコーディング宣言とは、XML文書で使われている文字エンコーディングを知らせる宣言のこと」と解釈できる。EncodingDeclの定義は以下で示される。

EncodingDecl ::= S 'encoding' Eq ( '"' EncName '"' | "'" EncName "'" )
EncName ::= [A-Za-z] ( [A-Za-z0-9._] | '-' )"

文書実体では、エンコーディング宣言はXML宣言の一部である。EncNameは、使われているエンコーディングの名前である。

In the document entity, the encoding declaration is part of the XML declaration. The EncName is the name of the encoding used.

参照元:4.3.3 実体で使われる文字エンコーディング Character Encoding in Entities

XML文書は以下で示されるようにUTF-8かBOMあり(後述)のUTF-16を既定の文字エンコーディングとしている。これら以外の文字エンコーディングである場合、エンコーディング宣言は必須である。

外部の文字エンコーディング情報(MIMEヘッダなど)が無いのであれば、UTF-8とUTF-16以外のエンコー ディン グで記録された解析対象実体は、エンコーディング宣言を含むテキスト宣言(4.3.1 テキスト宣言 The Text Declaration参照)から始まらなければならない(must)。

In the absence of external character encoding information (such as MIME headers), parsed entities which are stored in an encoding other than UTF-8 or UTF-16 must begin with a text declaration (see 4.3.1 The Text Declaration) containing an encoding declaration:

参照元:4.3.3 実体で使われる文字エンコーディング Character Encoding in Entities

UTF-8とUTF-16はバイトオーダーマーク(BOM:Byte Orger Mark)をつけることができる。以下で示されるように、XML文書ではUTF-8のBOMはあってもなくてもよいが、UTF-16のBOMは必須である。

UTF-16でエンコードされた実体は、[ISO/IEC 10646:2000]の付録Hや、Unicode [Unicode]のセクション16.8で説明されているバイトオーダーマーク(Byte Order Mark、BOM。ZERO WIDTH NO-BREAK SPACE文字(#xFEFF)の事)から始まらなければならない(must)。UTF-8でエンコードされた実体は、バイトオーダーマークから始まっても良い(may)。

Entities encoded in UTF-16 must and entities encoded in UTF-8 may begin with the Byte Order Mark described by Annex H of [ISO/IEC 10646:2000], section 16.8 of [Unicode] (the ZERO WIDTH NO-BREAK SPACE character, #xFEFF).

参照元:4.3.3 実体で使われる文字エンコーディング Character Encoding in Entities

文字エンコーディングにUTF-8とBOMありUTF-16を使えば、エンコーディング宣言を省略できるが、以下で示されるように将来のことを考えて指定したほうがよい。

また、現在はエンコーディング方法を決める為にエンコーディング宣言を使う事が必要とされない場合もあるが、将来的にはそれらの場合でもエンコーディング宣言が必要になるような新しい文字エンコーディングが作られる事もあり得る。

Also, it is possible that new character encodings will be invented that will make it necessary to use the encoding declaration to determine the encoding, in cases where this is not required at present.

参照元: F.1 外部エンコーディング情報を使わない検知 Detection Without External Encoding Information - Extensible Markup Language (XML) 1.0 (第五版)

また、XML文書の文字エンコーディングには"UTF-8"を使うのがいい。理由は以下2点だ。

  • UTF-8だとBOMがあってもなくてもよいため。UTF- 16は必ずBOMが必要なのでユーザー側での設定が紛らわしい。
  • 以下で文書の交換においてUTF-8が推奨されている。

エンコーディング宣言では、値"UTF-8"、"UTF-16"、"ISO-10646-UCS-2"、及 び"ISO- 10646-UCS-4"は、UnicodeとISO/IEC 10646の様々なエンコーディングやトランスフォーメーションに対して使われる事が望ましい(should)。

In an encoding declaration, the values "UTF-8", "UTF-16", "ISO-10646-UCS-2", and "ISO-10646-UCS-4" should be used for the various encodings and transformations of Unicode / ISO/IEC 10646.

参照元:4.3.3 実体で使われる文字エンコーディング Character Encoding in Entities

XMLパーサーが文字エンコーディングの判定を楽にできるようにUTF-8で書いたXML文書であっても encoding="UTF-8"は書いておこう。

SDDecl?

SDDeclはスタンドアローン文書宣言(SDDecl)である。

スタンドアローン宣言という言葉には以下の定義がある。

スタンドアローン文書宣言はXML宣言の構成要素として現れる事があり、文書実体の外や、パラメータ実体の中に、文書の内容に影響するような宣言があるかどうかを知らせる。

The standalone document declaration, which may appear as a component of the XML declaration, signals whether or not there are such declarations which appear external to the document entity or in parameter entities.

参照元: 2.9 スタンドアローン文書宣言 Standalone Document Declaration - Extensible Markup Language (XML) 1.0 (第五版)

このことから、「スタンドアローン宣言とは、XML文書が単一ファイルとして独立しているかどうかを知らせる宣言のこと」 と解釈できる。上記定義で は「文書の内容に影響するような」とあるように、文書の内容に影響がなければ、たとえ外部に宣言があっても無視すると解釈できる。

スタンドアローン宣言(SDDecl)は以下で定義される。

SDDecl ::= S 'standalone' Eq ( ( "'" ( 'yes' | 'no' ) "'" ) | ( '"' ( 'yes' | 'no' ) '"' ) )

例:

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

スタンドアローン宣言の属性値はyesnoがあり、以下の意味となる。

  • yes:外部マークアップ宣言が存在しないことを示す。
  • no:外部マークアップ宣言が存在するか、存在するかもしれないことを示す(既定値)。

スタンドアローン宣言の属性については以下の説明がある。

外部マークアップ宣言が一切無ければ、スタンドアローン文書宣言は何ら意味を持たない。外部マークアップ宣言はあるもののスタンドアローン文書宣言が無い時は、値"no"が指定されたものと見なされる。

If there are no external markup declarations, the standalone document declaration has no meaning. If there are external markup declarations but there is no standalone document declaration, the value "no" is assumed.

参照元: 2.9 スタンドアローン文書宣言 Standalone Document Declaration - Extensible Markup Language (XML) 1.0 (第五版)

また、スタンドアローン宣言について解説された記事において以下の解説がある。

standalone="yes"の文書が外部のファイルを参照することはありえないので、yesとnoを区別する必要がない。

つまり、事前に外部への参照の必要性が判明していれば、それによって処理を最適化できる可能性があるということだ。

参照元:XMLを学ぼう(9):Standaloneと究極の外部非依存文書 - @IT

XML 1.0において、スタンドアローン宣言(SDDecl)はXML宣言(XMLDecl)でしか使われず、外部マークアップ宣言が存在すれば自動 的に必要な設定であるstandalone="no"が設定されるので、明示的に書く必要がない。したがって、パフォーマンスを最適化する必要があるときだけ、必要に応じて明示的にyes|noを設定すればよい。

Q&A

前節までで、XML宣言の各部品の説明と、書くべき内容について説明してきた。ここでは、冒頭で掲げた5の疑問にQ&A形式で回答していく。また、その際に重複になるが根拠となる勧告文書の該当箇所も掲載した。

Q1. XML宣言を書くべきか?

A1. XML宣言は書くべき。勧告文書でXML宣言の記述が推奨されており、XML文書のバージョンと文字エンコーディングを明確にできる。また、XML宣言によりXMLパーサーに必要な情報が渡され正常な動作を期待しやすい。

根拠1-1:

[Definition: XML文書は、使われるXMLのバージョンを指定するXML宣言から始まる事が望ましい(SHOULD)。 ]

[Definition: XML documents SHOULD begin with an XML declaration which specifies the version of XML being used.]

参照元: 2.8 プロローグと文書型宣言 Prolog and Document Type Declaration - Extensible Markup Language (XML) 1.0 (第五版)

Q2. XML宣言のversionには何を使うべきか?

A2. 1.0を使い、version="1.0"とすべき。

根拠2-1:XML 1.0文書で書くならば1.0とすべき。

VersionNum生成規則は'1.x'の形であればあらゆるバージョン番号にマッチするが、XML 1.0文書が'1.0'以外のバージョン番号を指定する事は望ましくない(should not)。

Even though the VersionNum production matches any version number of the form '1.x', XML 1.0 documents should not specify a version number other than '1.0'.

参照元:2.8 プロローグと文書型宣言 Prolog and Document Type Declaration - Extensible Markup Language (XML) 1.0 (第五版)

根拠2-2:XML 1.1(第二版)ではXMLの生成プログラムはXML 1.0を生成することを推奨している。

XMLを生成するプログラムは、 XML 1.1特有の機能が必要とされない限り、 XML 1.0を生成する事が望ましい(SHOULD)。

Programs which generate XML SHOULD generate XML 1.0, unless one of the specific features of XML 1.1 is required.

参照元: 5.1 妥当性を検証するプロセッサとしないプロセッサ Validating and Non-Validating Processors - Extensible Markup Language (XML) 1.1 (第二版)

Q3. XML文書の文字エンコーディングとXML宣言のencodingの値は何を選べばよいか?

A3. XML文書の文字エンコーディングはUTF-8にすべき。また、XML宣言のencoding属性は省略せずにencoding="UTF-8"と記述すべき。

根拠3-1:XML文書の文字エンコーディングをUTF-8にすべき理由1。

エンコーディング宣言では、値"UTF-8"、"UTF-16"、"ISO-10646-UCS-2"、及 び"ISO-10646-UCS- 4"は、UnicodeとISO/IEC 10646の様々なエンコーディングやトランスフォーメーションに対して使われる事が望ましい(should)。

In an encoding declaration, the values "UTF-8", "UTF-16", "ISO-10646-UCS-2", and "ISO-10646-UCS-4" should be used for the various encodings and transformations of Unicode / ISO/IEC 10646.

参照元:4.3.3 実体で使われる文字エンコーディング Character Encoding in Entities - Extensible Markup Language (XML) 1.0 (第五版)

根拠3-2:XML文書の文字エンコーディングをUTF-8にすべき理由2。

XML文書をUTF-16でエンコーディングするときは、必ずバイトオーダーマーク(BOM:Byte Order Mark)が必要である。しかし、UTF-8には、BOMがあってもなくてもよい。つまり、UTF-8の方が受けが広くユーザーに優しい。

UTF-16でエンコードされた実体は、[ISO/IEC 10646:2000]の付録Hや、Unicode [Unicode]のセクション16.8で説明されているバイトオーダーマーク(Byte Order Mark、BOM。ZERO WIDTH NO-BREAK SPACE文字(#xFEFF)の事)から始まらなければならない(must)。UTF-8でエンコードされた実体は、バイトオーダーマークから始まっても良い(may)。

Entities encoded in UTF-16 must and entities encoded in UTF-8 may begin with the Byte Order Mark described by Annex H of [ISO/IEC 10646:2000], section 16.8 of [Unicode] (the ZERO WIDTH NO-BREAK SPACE character, #xFEFF).

参照元:4.3.3 実体で使われる文字エンコーディング Character Encoding in Entities - Extensible Markup Language (XML) 1.0 (第五版)

根拠3-3:XML宣言のencoding属性を省略すべきでない理由。

また、現在はエンコーディング方法を決める為にエンコーディング宣言を使う事が必要とされない場合もあるが、将来的にはそれらの場合でもエンコーディング宣言が必要になるような新しい文字エンコーディングが作られる事もあり得る。

Also, it is possible that new character encodings will be invented that will make it necessary to use the encoding declaration to determine the encoding, in cases where this is not required at present.

参照元: F.1 外部エンコーディング情報を使わない検知 Detection Without External Encoding Information - Extensible Markup Language (XML) 1.0 (第五版)

Q4. XML宣言のstandalone属性は書くべきか?

A4. パフォーマンスが重要な用途でない限り、XML宣言のstandalone属性は書くべきでない。

根拠4-1:

外部マークアップ宣言が一切無ければ、スタンドアローン文書宣言は何ら意味を持たない。外部マークアップ宣言はあるもののスタンドアローン文書宣言が無い時は、値"no"が指定されたものと見なされる。

If there are no external markup declarations, the standalone document declaration has no meaning. If there are external markup declarations but there is no standalone document declaration, the value "no" is assumed.

参照元: 2.9 スタンドアローン文書宣言 Standalone Document Declaration - Extensible Markup Language (XML) 1.0 (第五版)

Q5. XML宣言の終端である?>の直前に空白を入れるべきか?

A5. XML宣言の終端である?>の直前には空白を入れない方がいい。この位置での空白は完全に任意であり、あってもなくてもかまわない。勧告文書ではこのような属性や値に使われない空白をどうすべきかについて明記されていない。

しかし、勧告文書で掲載されている例では以下の2例を除き、省略可能なホワイトスペースは基本的に省略されていた。

  1. 勧告文書で掲載されているXML宣言の例では、終端に空白が存在する例は全7個中1個しかなかった。
  2. XML宣言の終端と同様にあってもなくてもよい空白をもつEqの例(記号=の前後の空白)では、前後の空白が存在する例が全27個中1個しかなかった。

このことから、勧告文書としては、基本的に省略可能なホワイトスペースは省略すべきという方針が伺える。したがって、この方針にのっとりXML宣言の終端の空白は入れないほうがいいだろう。

根拠5-1:XML 1.0(第五版)の勧告文書でXML宣言の例として終端にホワイトスペースがある唯一の例。

<?xml version="1.0" encoding="UTF-8" ?>
                    <!DOCTYPE greeting [ <!ELEMENT greeting (#PCDATA)>
                    ]>
                    <greeting>Hello, world!</greeting>

参照元: Extensible Markup Language (XML) 1.0 (Fifth Edition)

根拠5-2:XML 1.0(第五版)の勧告文書でEqが使われている例全27個中ホワイトスペースがある唯一の例。

a= "&#xd;&#xd;A&#xa;&#xa;B&#xd;&#xa;"
参照元:Extensible Markup Language (XML) 1.0 (Fifth Edition)

結論

結論として、最も推奨されるべき正しいXML宣言は、冒頭に示したとおり以下の内容をファイルの1行目に記述することだ。

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

そしてXML文書の文字エンコーディングをUTF-8する。これにより、どんなXML文書でも通用するXML宣言を記述できる。

0 件のコメント:

コメントを投稿