Modularization of XHTML の第二版の草案が公開されました。以前まで Modularization of XHTML™ in XML Schema として公開されていた内容も統合され、DTD モジュールの定義も XML Schema との併用を考慮したものに調整されています。その他は基本的に微細なエラーの修正がされているだけなのですが、一点、非常に重要な新しい仕様が定義されています。
ご存知の方はご存知のように、現在の XHTML では汎用属性も名前空間的にローカルで、すなわちそれぞれの要素型に固有の属性として宣言されています。このような定義は、本来名前空間的には好ましいものではありません。また、このような定義がなされていると、他の名前空間に属する要素に対して XHTML の汎用属性を付与する、というような利用方法を用いることが不可能になってしまいます。
この不便を解消するべく、新しい M12N 仕様では汎用属性をグローバル属性として利用できるように定義されています。今まで「xml:id がないと不便」と言っていた人も、 暫定的に xhtml:id を使うことができますし、それ以上に、xhtml:class や xhtml:title と言った非常に有用な語彙が他の名前空間でも使えるようになります。素晴らしい。
ただまぁ、このグローバル属性の DTD での実装状況にはまだちょっと難があるのですが (global attrib の DTD 実装についてのメモを参照)。
以下細かな変更など。
xml:lang=""
というのが valid になった。(PCDATA | Heading | Block | List)*
から (Heading | Block | List)*
に (でも DTD 実装は (Heading | Block | List)+
だ)。(PCDATA | Inline)+
から (PCDATA | Inline)*
に (当たり前)。preserve
で固定、本文では修正されていないが、DTD がそうなっているので多分修正し忘れだろう)。その他、報告済み errata とか。以下未報告の errata とかのメモ。
-//W3C//SGMLDOCUMENT XHTML 1.1//EN
とか、書けなくはないが)。グローバル属性の DTD 実装についてのメモの件だけど、具体的にはこんな感じでどうかと思うのだが。XHTML.prefixed で要素名を default のままにするか prefix するか決定し、XHTML.global.attrs.prefixed で汎用属性を local にするか global にするか決定するのは元の仕様の通り。
ところで、M12N SE が PER じゃなく Working Draft からスタートしてるのは M12N in XML Schema との調整のためなのだろうが、そもそもこの仕様を M12N in XHTML に対する SE と呼ぶのはちょっと無理があるような気がする。バージョンナンバーを改めて、1.1 とかにする方が適切なのではなかろうか。
MSXML が「無効な文字で名前が始まりました」というエラーを返す件ですが、結論から述べると http://www.w3.org/TR/xhtml-modularization/DTD/xhtml-special.ent
のエラーが原因です。一般実体 lt
, amp
の定義を上書きするが、もしくは -//W3C//ENTITIES Special for XHTML//EN
のシステム識別子をエラーのないバージョンのもの (例えば http://www.w3.org/TR/xhtml1/DTD/xhtml-special.ent
) に上書きしてやれば解消します。
<!DOCTYPE html PUBLIC "-//WAPFORUM//DTD WML 2.0//EN" "http://www.wapforum.org/dtd/wml20.dtd" [ <!ENTITY % xhtml-inlpres.mod PUBLIC "-//W3C//ELEMENTS XHTML Inline Presentation 1.0//EN" "http://www.w3.org/TR/xhtml-modularization/DTD/xhtml-inlpres-1.mod" > <!ENTITY % xhtml-special PUBLIC "-//W3C//ENTITIES Special for XHTML//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml-special.ent" > ]>
<!DOCTYPE html PUBLIC "-//WAPFORUM//DTD WML 2.0//EN" "http://www.wapforum.org/dtd/wml20-flat.dtd" [ <!ENTITY lt "&#60;" > <!ENTITY amp "&#38;" > ]>
なお、19日に触れた通り、このエラーは Modularization of XHTML の第二版草案では修正されています。この第二版が勧告されればモジュール群も上書きされることになりますから、単にフラット DTD を参照するだけでも MSXML で解析できるようになるでしょう。
# 微妙に続きます。名前空間と PSVI、M12N のバグと MSXML、定義済み文字実体。
MSXML で WML を扱った際に、面倒なので WML の語彙を使わずに (WML の語彙なんてそもそも知らないし) 以下のようなサンプルを解析対象にしようとしました。
<?xml version="1.0" encoding="utf-8" ?> <!DOCTYPE html PUBLIC "-//WAPFORUM//DTD WML 2.0//EN" "http://www.wapforum.org/dtd/wml20.dtd" [ <!ENTITY % xhtml-inlpres.mod PUBLIC "-//W3C//ELEMENTS XHTML Inline Presentation 1.0//EN" "http://www.w3.org/TR/xhtml-modularization/DTD/xhtml-inlpres-1.mod" > <!ENTITY lt "&#60;" > <!ENTITY amp "&#38;" > ]> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <title>MSXML test</title> </head> <body> <p>...</p> </body> </html>
ところが、MSXML はこれにエラーを返しました。曰く、接頭辞 wml:
が宣言されていない、と。WML の語彙を書いていないのに、です。
はじめ、以前に古林さんの仰っていた不具合の関連かと思ったのですが、上の例に wml: に対する宣言を追加してやれば一目瞭然、これは body 要素にデフォルト値付きで WML の属性 (wml:newcontext="false"
) が宣言されているためでした。
xmlns:wml も wml:newcontext も外部パラメタで宣言されているわけで、MSXML 的には処理に困る要因はないわけですが、よく考えると確かに仕様上はこういうのも NSC を満たさないことになってます。
Namespace constraint: Prefix Declared
The namespace prefix, unless it is xml
or xmlns
, MUST have been declared in a namespace declaration attribute in either the start-tag of the element where the prefix is used or in an ancestor element (i.e. an element in whose content the prefixed markup occurs). Furthermore, the attribute value in the innermost such declaration MUST NOT be an empty string.
This constraint may lead to operational difficulties in the case where the namespace declaration attribute is provided, not directly in the XML document entity, but via a default attribute declared in an external entity. Such declarations may not be read by software which is based on a non-validating XML processor. Many XML applications, presumably including namespace-sensitive ones, fail to require validating processors. If correct operation with such applications is required, namespace declarations
MUST be provided either directly or via default attributes declared in the internal subset of the DTD.
文脈からすれば、後半の「名前空間宣言は外部パラメタのデフォルト値に頼っちゃダメだ」というのは「外部パラメタのデフォルト値による名前空間宣言は意味を持たない」程度を意図したものであったろうと思われるのですが…。しかしながら、この後半で実際に述べられているのは、あくまで「外部パラメタに名前空間宣言となるデフォルト値付き属性定義がある場合は、non-validating processor にも処理可能な状態にしなければならない (MUST)」ということに過ぎず、実際にその名前空間の語彙が使われているか否か (あるいはどのように使われているのか) ということは無関係になってしまっています。
ということは、今回の MSXML の挙動は仕様に適合しているものと言えますし、それどころか本来は wml:newcontext
なんかなくとも xmlns:wml
を宣言しなければならないということになります。これで編者の意図通りなのかは甚だ疑問ですが…。
以下は WML 2.0 のエラーについて #2 の経緯というか余談です。
前に「MSXML に XHTML 1.1 を解析させる」という記事を書きましたが、この中で公開していたモジュール DTD ベースのサンプルは、本文中にある通り実際には MSXML で解析可能であることを確認していませんでした。これは、当時僕が使っていた首都大東京 (どこ) のマシンが非力であったせいか、解析中に MSXML 異常終了してしまっていたためです。
その後、他の環境でこのサンプルの処理を試みたところ、こんなエラーが返ることを知りました。
無効な文字で名前が始まりました。リソース 'http://www.satoshii.org/markup/samp/2003/xhtml11-msxml-m12n' の実行エラーです。ライン 1、位置 2
&&
このエラーはフラット DTD ベースのサンプルで生じないものだったため、僕はファイルの数が多すぎるために変なエラーを返しているのかなぁ、処置なしだなぁなどと思っていました。
さて。先日、上で参照したまなさんの記事を読んで、まぁ同じことだろう、フラット DTD を使えば問題は起こるまい、と思いました。というか、そもそもフラット DTD を参照すれば xhtml-inlpres.mod
の識別子を変更する必要もないじゃないか、とも。
それで、昨日久し振りにウィンドウズマシンに触れる機会があったので、件のエラーについてようやく実物の MSXML でテストすることができました。したらば、WML 2.0 ではフラット DTD を参照しても同じエラーを返すのですよ。MSXML は。
この段に至り、ようやく僕もアレはファイルの数とか関係なくて、文字通りの構文的なエラーなのだろうと気付いたわけです。で、改めて WML 2.0 のフラット DTD をさーっと眺め、文字実体モジュールの辺りにさしかかったところで思い至ったわけです。M12N の文字実体と言えば FAQ なアレがあるじゃないか、と。
When trying to validate a DTD that include this package the validation compains of an error for "&&"
. It looks like the following two definitions are not correct:
<!ENTITY lt "&<" ><!-- less-than sign, U+003C ISOnum -->
<!ENTITY amp "&&" ><!-- ampersand, U+0026 ISOnum -->
というか &
二個並びの時点で気付かなかったのは我ながらヌルいなぁという感じなのですが、XHTML 1.1 のフラット DTD ではこの問題が解消されていたもので、何となく XHTML 1.1 は影響を受けていないような錯覚をしてました (多分あのフラット DTD に展開した環境では、-//W3C//ENTITIES Special for XHTML//EN
を http://www.w3.org/TR/xhtml1/DTD/xhtml-special.ent
に紐付けしていたのでしょう)。
しかし、微妙に気になるのが、なぜ実際に amp や lt を参照したわけでもないのにエラーになったのか、ということ。「ライン 1、位置 2」という表示もしっくりこないものがありますし、もしかすると MSXML は内部的に何らかの XML を利用していて、その中で amp への参照が現れてエラーになったのかなぁ…などと思ったり。
実体値 - SuikaWiki によると、MSXML は実体宣言を処理する際に一般実体の実体値を内容として構文解析
してしまうそうです。で、しかもその実体値が (内容としての) 誤りを含んでいた場合にエラーメッセージとして出力される URI と位置が変なふうに表示されている、と。
つまるところ、件のエラーメッセージの内容からも何となく判るように、定義済み文字実体に関する仕様書の記述から直接的にエラーとされているわけではないみたいですね。
上の Modularization of XHTML のエラー話の続き。このエラーは少なくとも editorial error ではありますが、実際問題 XML/SGML としてはどうなのか、ということを以下ちょっと考えてみます。
Web SGML 的には、定義済みデータ文字実体は文書型宣言の内部サブセットの先頭で宣言されているものとして扱うことになっています。つまり、件の誤った宣言のようなものが実際に amp の値を上書きすることはありません。あくまで実体宣言としての構文検証の対象にはなりますが、アクティブな意味は持たないわけです。
で、あの実体宣言は実体宣言の構文としては正しいものになっていますから、Web SGML 的には妥当な文書として扱われます。例えば、W3C のバリデータは XHTML 1.1 や XHTML Basic の文書に対してエラーを返すことはないはずです (実際にはカタログで正しい版のモジュールを参照しているのですが、M12N のものを参照させても問題なく処理します)。
それでは XML ではどうなのでしょう。実は、XML にはこの辺りについての厳密な規定はありません。定義済み文字実体に対し、「相互運用性のためには DTD でも実体宣言せよ」との注記こそあるものの、その実体宣言がどのような意味を持つのか、すなわち XML プロセサに対してどう働くのかといった記述は全くないのです。
このため、「(1)宣言の解析はするが実体値を上書きすることはない」とか (Web SGML 的にはこれが正しい)、「(2)定義済み実体の値を上書きする」とか (MSXML はこれ?)、「(3)実体宣言そのものを無視する」などといった現実の実装はプロセサの開発者の解釈に依存しているのが現状です。
一応 XML が Web SGML のサブセットである以上、仕様として (2) (3) はありえず、必然的に (1) が正しいと言えるのですが、これは XML 自身で明記しておく必要のある事柄ではないかと思います。
SuikaWiki でご指摘いただきましたが、XML の仕様書にちゃんと規定がありますね。失礼しました。
If the entities lt
or amp
are declared, they MUST be declared as internal entities whose replacement text is a character reference to the respective character (less-than sign or ampersand) being escaped; the double escaping is REQUIRED for these entities so that references to them produce a well-formed result.
なんか MUST じゃないと勘違いしてました。二重エスケープ云々すら (RFC2119 な) REQUIRED として言及されてるのに…。
# ということは、XHTML 1.1 でも XHTML Basic だの SVG Basic だのと同様、仕様書のママの DTD を参照してはならないということですね。合掌。