MSXMLと名前空間の指定があるXML [プログラミング]
Windows環境で、XMLを操作するプログラムを作ろうと思った場合、MSXMLを使うのが(何もインストールする必要が無いという理由で)簡単です。
一方、XMLには名前空間(namespace)という機能があります。
そこで、名前空間の指定があるXMLデータをMSXMLで操作することにします。
名前空間の指定があるXMLとして、こんなXMLデータを用意しました。
<?xml version="1.0" encoding="Shift_JIS"?> <xhtml:html xmlns:xhtml="http://www.w3.org/1999/xhtml"> <xhtml:head> <xhtml:title>XHTML sample</xhtml:title> </xhtml:head> <xhtml:body> test </xhtml:body> </xhtml:html>
一般的な「MSXMLを使ってXMLからデータを取得する方法」に従って、プログラムを書いて見ました。
#import <msxml6.dll> int main() { ::CoInitialize(NULL); try { MSXML2::IXMLDOMDocument3Ptr doc; doc.CreateInstance(__uuidof(MSXML2::DOMDocument60)); doc->async = VARIANT_FALSE; doc->load("test.xml"); MSXML2::IXMLDOMNodePtr node = doc->selectSingleNode("/xhtml:html/xhtml:body"); if (node) { std::cout << static_cast<const char*>(node->text) << "\n"; } else { std::cout << "Unknown tag\n"; } } catch (_com_error& e) { std::cout << e.ErrorMessage() << "\n"; } ::CoUninitialize(); return 0; }
ところがどっこい。
コレでは動きません。
_com_error
が例外で投げられます。
(原因は「エラーを特定できません」です)
XMLのタグにある「xhtml:
」の部分は、名前空間を表す接頭辞なので、実は指定しなくても良かったりするのだろうか……。
MSXML2::IXMLDOMNodePtr node = doc->selectSingleNode("/html/body");
例外は出なくなりましたが、selectSingleNode()
が NULL を返します。
やっぱり、名前空間はしっかり指定しないといけませんな。
ちなみに、正解はこちら。
doc->setProperty("SelectionNamespaces", "xmlns:h='http://www.w3.org/1999/xhtml'"); MSXML2::IXMLDOMNodePtr node = doc->selectSingleNode("/h:html/h:body");
名前空間の接尾辞は、XMLデータと合わせる必要はありません。
(といっても、合わせておいた方が無難でしょうが……)
あと、デフォルト名前空間では、きちんと動作しないので、ちゃんと接尾辞はつける必要がありそうです。
(読み込み対象のXMLがデフォルト名前空間を使って記述されていても)
// コレは NG。selectSingleNode()がNULLを返す。 doc->setProperty("SelectionNamespaces", "xmlns='http://www.w3.org/1999/xhtml'"); MSXML2::IXMLDOMNodePtr node = doc->selectSingleNode(<"/html/body");
今日の一冊 | |
|
2009-11-18 07:33
nice!(0)
コメント(0)
トラックバック(0)
コメント 0