- PR -

MSXMLでデフォルト名前空間を取り扱う方法

投稿者投稿内容
縞芋
会議室デビュー日: 2005/08/03
投稿数: 9
投稿日時: 2006-04-04 15:34
お世話になります。縞芋と申します。
MSXMLに詳しい方に、是非お尋ねしたい事があります。

MSXMLで、デフォルト名前空間(xmlns="foo")を指定しているXMLデータを読込み、
DOM操作でノードを取得しようとしたら、ノードが取得できません。

プログラム言語はC++を利用しています。
開発環境はVC++7.1、パーサはMSXML4.0です。

現在は以下の通りに行っています。

== C++コード ==
MSXML2::IXMLDOMDocument2Ptr doc;
doc.CreateInstance(MSXML2::CLSID_DOMDocument40);
HRESULT hr = doc->load("test.xml");
if (FAILED(hr)) { <略> };

doc->setProperty(L"SelectionNamespaces", "xmlns='foo'");

MSXML2::IXMLDOMElementPtr root;
doc->get_documentElement(&root);

MSXML2::IXMLDOMNodeListPtr childlist;
root->get_childNodes(&childlist);

MSXML2::IXMLDOMNodePtr child;
childlist->item(index, &child); <-- ここでエラー発生


== XMLデータ ==
<?xml version="1.0" encoding="UTF-8"?>
<root xmlns="foo">
<child1/>
<child1/>
</root>


どうやらget_childNodesの段階で子ノードが取得できていない様で
空のノードリストからノードを取ろうとするからエラー、と言うことみたいなのです。

setPropertyの辺りが怪しいと思って色々調べてみたのですが
核心に至る情報が入手できず、最後の手段として
ここに投稿してみました。

どなたか、こういった方法で似たような事を解決した等の
情報がありましたら、是非とも教えてください。
宜しくお願い致します。
MMX
ぬし
会議室デビュー日: 2001/10/26
投稿数: 861
投稿日時: 2006-04-06 11:01
doc->setProperty(L"SelectionNamespaces", "xmlns='foo'");
は 必要ですか?
XPath Queries
を全然使っていない、場合でも。
縞芋
会議室デビュー日: 2005/08/03
投稿数: 9
投稿日時: 2006-04-06 20:15
ご返答ありがとうございます!

>doc->setProperty(L"SelectionNamespaces", "xmlns='foo'");
>は 必要ですか?
>XPath Queries
>を全然使っていない、場合でも。

XPath Queriesは初めて聞きますので分かりませんが、
setProperty無しでデフォルト名前空間を割り当てたXMLを読込むと
ノードが取得できませんでした。
上記の様にsetPropertyを行っても同じでした。

"xmlns:test='foo'"の様に接頭語をXMLの要素、名前空間に付けると
setPropertyで設定すれば取得できました。

普通はsetProperty無しでデフォルト名前空間を割り当てたXMLを読んでも
ノードの取得等DOM操作が出来るものなのでしょうか?

早速、XPath Queriesの方も調査してみます。
MMX
ぬし
会議室デビュー日: 2001/10/26
投稿数: 861
投稿日時: 2006-04-06 21:04
ぴったりに近いのは 検索できました
PRB: MSXML 4.0: Matching Nodes Are Not Returned When You Run XPath Queries Against XML Documents that Specify a Default Namespace Declaration
http://support.microsoft.com/default.aspx?scid=kb;en-us;313372
でも、名前空間に関係なく、1ステップづつ たどるのにも
影響するとは 思えません
==================
MSXML6 ではどうでしょう

[ メッセージ編集済み 編集者: MMX 編集日時 2006-04-06 21:05 ]
縞芋
会議室デビュー日: 2005/08/03
投稿数: 9
投稿日時: 2006-05-09 15:33
諸事情により返答が遅くなりました。
申し訳ありません。

>MMXさん
ご返答ありがとうございます!

教えていただいた頁の方法等色々試してみた所、
普通にAPIを使ってノードを辿る事には問題がありませんでしたが
どうやらgetElementsByTagNameやselectNodes等、
与えた式に該当するノード群を取得する様なAPIを利用した場合に
ノードが取得できない様でした。(該当ノード無しの為、空NodeListが返る)

Prefix無し名前空間を設定したXMLデータを読込み、
MSXMLのsetPropertyで適当なPrefixとURIを設定する方法と
単純にPrefix抜きでsetPropertyでURIを設定したした方法を試した結果
両方ともgetElementsByTagNameやselectNodesといった
APIではノード集合が取得できませんでした。

当たり前ながら、Prefix有り名前空間を設定したXMLデータを読込んで
setPropertyでPrefixとURIを設定すると
getElementsByTagNameやselectNodesでノード集合が取得できました。

やはり、無理にデフォルト名前空間を使うより
Prefix付き名前空間を設定したXMLデータを取り扱った方が
よさそうな気がしてきましたが…。


>MSXML6ではどうでしょう
今回はMSXML4での実装を考えて行っているので
MSXML6の利用は考えていません。
今後の為にMSXML6の調査もしてみます。


引き続き、自分なりに調査を進めて行きたいと思います。
御意見ありがとうございました!
MMX
ぬし
会議室デビュー日: 2001/10/26
投稿数: 861
投稿日時: 2006-05-09 17:23
doc->setProperty(L"SelectionNamespaces", "xmlns='foo'");

XPath式を "//child1"
ではなく

doc->setProperty(L"SelectionNamespaces", "xmlns:DEFAULT='foo'");

XPath式を "//DEFAULT:child1"
ではどうでしょう。

1.名前空間の照合は名前空間プレフィックスではなく名前空間 URI でする、
2.XPath式には検索対象文書のデフォルト空間は、しみ込んで行かない(知らない→使えない)。プリフィックス無しは "" のURI
XSLTの書き方ではそうです
縞芋
会議室デビュー日: 2005/08/03
投稿数: 9
投稿日時: 2006-05-16 16:54
>MMXさん
いつもご返答ありがとうございます!

問題になっていた部分が漸く分かってきました。

MMXさんが教えてくださった方法で、XPath式を利用した場合はノードを取得する事が出来ました。
→setelctNodes, selectSingleNode


どうやら私のお聞きした質問の内容自体が少々間違っていた様で
「デフォルト名前空間が指定されているインスタンスを読み込んだ場合にgetElementsByTagNameでノードが取得できない」
と言う事でした。
ややこしくなってしまってすみません。

MSXMLのgetElementsByTagName仕様にはなにやら名前空間は認められないか、サポートされていないってなっていますが、
インスタンスの名前空間やノードにPrefixが指定してあれば問題ないのに
デフォルト名前空間が使えないのは何故なのでしょう…。

CreateInstance時に指定するIDをCLSID_DOMDocument40ではなく、
CLSID_DOMDocument30にする事でこの問題は解決しましたが
根本解決にはなっていないのでまだ調査が必要です。
(そもそも何故40が駄目で30が良いのかが分かっていません)

setPropertyで何か指定する必要があるのでしょうか。
MMX
ぬし
会議室デビュー日: 2001/10/26
投稿数: 861
投稿日時: 2006-05-16 19:54
「名前空間の有効範囲」は入れ子にできて
http://www.atmarkit.co.jp/fxml/rensai2/xmlmaster13/master13.html
[code]
<p xmlns="ppp"><b>
<h xmlns="qqq"><b/></h></b></p>
[/code]
プリフィックスの無い要素の名前空間URIは一意でない、XMLを作れます。

それを検索対象にした場合、XPath のプリフィックス無いものの名前空間URIは
あいまいになります。かな

スキルアップ/キャリアアップ(JOB@IT)