水無月ばけらのえび日記

bakera.jp > 水無月ばけらのえび日記 > 2010年のえび日記 > 2010年8月 > 2010年8月11日(水曜日)

2010年8月11日(水曜日)

XmlPreloadedResolverでXHTML1.1を処理する

公開: 2010年8月12日22時30分頃

W3CのDTDを取りに行きすぎるとBANされるという話がありますで紹介したXmlPreloadedResolverクラスですが、.NET Framework4から使えるようになっています。

DTDを取りに行かなくてもXHTMLをWell-formedなXMLとして扱うことはできるのですが、©などの実体参照が解釈できないという問題があります。XmlPreloadedResolverを使えば、無駄な通信をせずに実体参照も扱えるようになるので便利です。

というわけでさっそく試してみました。たとえば以下のようにすると、

XmlDocument doc = new XmlDocument();
doc.XmlResolver = new XmlPreloadedResolver(XmlKnownDtds.Xhtml10);

文書型宣言に http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd などのURLが出現しても、取りに行かずに解釈することができるようになります。これですべて解決……と思いきや、XmlKnownDtds列挙体 (msdn.microsoft.com)にはXHTML1.0とRSS0.91のものしかありません。XmlKnownDtds.All を指定した場合でも、以下のもので全てのようなのです。

何が困るって、XHTML1.1がどこにもないわけですよ。

とはいえ、諦めるのはまだ早いです。XmlPreloadedResolver.Add() を呼ぶと任意のUriとDTDのペアを追加できるようなので、XHTML1.1のDTDをローカルに置いてからこんな感じでやれば簡単に……。

FileInfo dtdFile = new FileInfo("xhtml11.dtd");
Uri dtdPublicUri = new Uri("http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd");

XmlPreloadedResolver xpr = new XmlPreloadedResolver();
using(FileStream fs = dtdFile.Open(FileMode.Open, FileAccess.Read, FileShare.Read)){
    xpr.Add(dtdPublicUri, fs);
}

……と思いきや、実際に使ってみたらこんな例外が。

System.Xml.XmlException: 'http://www.w3.org/TR/xhtml-modularization/DTD/xhtml-inlstyle-1.mod' を解決できません。

そういえば、XHTML1.1の特徴はモジュール化でしたね。

幸い、XHTML1.1にはモジュール化されたDTD群を合体させたxhtml11-flat.dtdがついているので、ローカルのxhtml11-flat.dtdを読ませるようにして解決しました。flat版があって良かったです……。

関連する話題: C# / .NET / プログラミング

最近の日記

関わった本など