- PR -

MSXML3.0で2つのDOMドキュメントを結合したいのですがappendChildで落ちます(.Net Frameworkでないです)

投稿者投稿内容
koara
ベテラン
会議室デビュー日: 2005/09/16
投稿数: 96
投稿日時: 2005-09-16 16:24
はじめまして koaraと申します。
閲覧ばかりでしたがはじめて書き込みさせて頂きます。
過去スレを見ましたが、importNodeを使った書き込みはあったのですが
どうしても解決できませんでした。

xml1の<rs:data>以下をxml2の<rs:data>以下に追加したいのですがうまくいきません。
vc++6.0にてコンパイルは出来るのですが、appendChildをすると実行時エラーで落ちてしまいます。

xml1.xml:

<xml xmlns:s="uuid:BDC6E3F0-6DA3-11d1-A2A3-00AA00C14882" xmlns:dt="uuid:C2F41010-65B3-11d1-A29F-00AA00C14882" xmlns:rs="urn:schemas-microsoft-com:rowset" xmlns:z="#RowsetSchema">
<s:Schema id="RowsetSchema">
<s:ElementType name="row" content="eltOnly" rs:CommandTimeout="30">
<s:AttributeType name="MACHINE" rs:number="1" rs:nullable="true" rs:write="true">
<s:datatype dt:type="string" rs:dbtype="str" dt:maxLength="8190"/>
</s:AttributeType>
<s:AttributeType name="INTIME" rs:number="3" rs:nullable="true" rs:write="true">
<s:datatype dt:type="string" rs:dbtype="str" dt:maxLength="8190"/>
</s:AttributeType>
<s:extends type="rs:rowbase"/>
</s:ElementType>
</s:Schema>
<rs:data>
<z:row MACHINE="APPLE" INTIME="2005/09/09 12:33:11"/>
<z:row MACHINE="DELL" INTIME="2005/09/05 11:13:12"/>
</rs:data>
</xml>

xml2.xml:

<xml xmlns:s="uuid:BDC6E3F0-6DA3-11d1-A2A3-00AA00C14882" xmlns:dt="uuid:C2F41010-65B3-11d1-A29F-00AA00C14882" xmlns:rs="urn:schemas-microsoft-com:rowset" xmlns:z="#RowsetSchema">
<s:Schema id="RowsetSchema">
<s:ElementType name="row" content="eltOnly" rs:CommandTimeout="30">
<s:AttributeType name="MACHINE" rs:number="1" rs:nullable="true" rs:write="true">
<s:datatype dt:type="string" rs:dbtype="str" dt:maxLength="8190"/>
</s:AttributeType>
<s:AttributeType name="INTIME" rs:number="3" rs:nullable="true" rs:write="true">
<s:datatype dt:type="string" rs:dbtype="str" dt:maxLength="8190"/>
</s:AttributeType>
<s:extends type="rs:rowbase"/>
</s:ElementType>
</s:Schema>
<rs:data>
<z:row MACHINE="NEC" INTIME="2005/09/09 02:03:01"/>
<z:row MACHINE="HP" INTIME="2005/03/09 11:32:31"/>
</rs:data>
</xml>

を結合して

<xml xmlns:s="uuid:BDC6E3F0-6DA3-11d1-A2A3-00AA00C14882" xmlns:dt="uuid:C2F41010-65B3-11d1-A29F-00AA00C14882" xmlns:rs="urn:schemas-microsoft-com:rowset" xmlns:z="#RowsetSchema">
<s:Schema id="RowsetSchema">
<s:ElementType name="row" content="eltOnly" rs:CommandTimeout="30">
<s:AttributeType name="MACHINE" rs:number="1" rs:nullable="true" rs:write="true">
<s:datatype dt:type="string" rs:dbtype="str" dt:maxLength="8190"/>
</s:AttributeType>
<s:AttributeType name="INTIME" rs:number="3" rs:nullable="true" rs:write="true">
<s:datatype dt:type="string" rs:dbtype="str" dt:maxLength="8190"/>
</s:AttributeType>
<s:extends type="rs:rowbase"/>
</s:ElementType>
</s:Schema>
<rs:data>
<z:row MACHINE="APPLE" INTIME="2005/09/09 12:33:11"/>
<z:row MACHINE="DELL" INTIME="2005/09/05 11:13:12"/>
<z:row MACHINE="NEC" INTIME="2005/09/09 02:03:01"/>
<z:row MACHINE="HP" INTIME="2005/03/09 11:32:31"/>
</rs:data>
</xml>



というDOMDocumentを作りたいです。
以下のようなソース(抜粋しました)になります。


source.cpp:

#import "C:\\Program Files\\Common Files\\System\\ADO\\msado15.dll" rename_namespace("MSXML2") rename("EOF", "EndOfFile")
#import "msxml3.dll" named_guids
using namespace MSXML2;


::CoInitialize(NULL);

IXMLDOMDocumentPtr pDoc_xml1;
IXMLDOMDocumentPtr pDoc_xml2;

//xml1.xml読み込み
pDoc_xml1.CreateInstance(__uuidof(DOMDocument30));
pDoc_xml1->put_async(VARIANT_FALSE);
pDoc_xml1->validateOnParse = FALSE;

pDoc_xml1->load( _variant_t("xml1.xml") );

//xml2.xml読み込み
pDoc_xml2.CreateInstance(__uuidof(DOMDocument30));
pDoc_xml2->put_async(VARIANT_FALSE);
pDoc_xml2->validateOnParse = FALSE;

pDoc_xml2->load( _variant_t("xml2.xml") );


IXMLDOMNode *pIXMLDOMNode1 = NULL;
IXMLDOMNode *pIXMLDOMNode2 = NULL;

//xml1
pIXMLDOMNode1 = pDoc_xml1->selectSingleNode("//z:row");

//xml2
pIXMLDOMNode2 = pDoc_xml2>selectSingleNode("//rs:data");

//xml1+xml2
pIXMLDOMNode2->appendChild(pIXMLDOMNode1);

アドバイスお願いします。



[ メッセージ編集済み 編集者: koara 編集日時 2005-09-16 16:26 ]

[ メッセージ編集済み 編集者: koara 編集日時 2005-09-16 16:27 ]

[ メッセージ編集済み 編集者: koara 編集日時 2005-09-16 16:31 ]

[ メッセージ編集済み 編集者: koara 編集日時 2005-09-16 16:32 ]
koara
ベテラン
会議室デビュー日: 2005/09/16
投稿数: 96
投稿日時: 2005-09-16 17:01
自己レスです。

IXMLDOMElementPtr ElementPtr1;
IXMLDOMElementPtr ElementPtr2;

//xml1
ElementPtr1 = pDoc_xml1->selectSingleNode("//z:row");

//xml2
ElementPtr2 = pDoc_xml2->selectSingleNode("//rs:data");

//xml1+xml2
ElementPtr2->appendChild(ElementPtr1);

pDoc_xml1->save("c:\\xml1.xml");
pDoc_xml2->save("c:\\xml2.xml");

とすることで1つは追加できましたが、複数追加するにはIXMLDOMNodeListPtr
を取得してfor文で取り出すしかないのでしょうか?
Vacant-Eyes
ベテラン
会議室デビュー日: 2004/08/15
投稿数: 97
投稿日時: 2005-09-16 17:54
ぱっと思いつく方法は・・・

@documentFragmentを作成
AXML2から追加したい部分のNodeListを作成
B@にAのノードをループでまわしてappendChild
CXML1の追加先ノード.appendChild(documentFragmentのClone)

めっちゃ走り書きです。
もっといい方法があるかも。
koara
ベテラン
会議室デビュー日: 2005/09/16
投稿数: 96
投稿日時: 2005-09-16 18:25
Vacant-Eyes様 レスありがとうございます。

documentFragmentというものの存在を初めて知りました。
自分なりに調べたのですが、普通はnodeをappendChildする場合ひとつずつ
しかできないのだけれど、
documentFragmentというものを経由することであたかもひとつのnodeのように
appendChildできるというものでしょうか。

そこで、

IXMLDOMDocumentFragmentPtr pFragmentPtr;

IXMLDOMNodeListPtr pNodeList;
IXMLDOMNode *pNode=NULL;

pNodeList = pDoc_xml->selectNodes("//z:row");
for(int i = 0; i < pNodeList->length; i++){
pNode = pNodeList->Getitem(i);
pFragmentPtr->appendChild(pNode);
}

//xml2
IXMLDOMElementPtr ElementPtr;
ElementPtr = pDoc_ado->selectSingleNode("//rs:data");
ElementPtr->appendChild(pFragmentPtr);

pDoc_xml->save("c:\\xml1.xml");
pDoc_ado->save("c:\\xml2.xml");

としてみたのですが、
pFragmentPtr->appendChild(pNode);
で落ちてしまいます。
MessageBox(NULL, pNode->text, NULL, MB_OK);
としても参照できないということはうまくノードを取得できてないのでしょうか?
koara
ベテラン
会議室デビュー日: 2005/09/16
投稿数: 96
投稿日時: 2005-09-16 19:00
IXMLDOMDocumentFragmentPtr pFp;
pFp = pDoc_xml->createDocumentFragment();

IXMLDOMNodeListPtr pNl;
IXMLDOMElementPtr pEm;

pNl = pDoc_xml->selectNodes("//z:row");
for(int i = 0; i < pNl->length; i++){
pEm = pNl->Getitem(i);
pFp->appendChild(pEm);
}


//xml2
pDoc_ado->selectSingleNode("//rs:data")->appendChild(pFp);

sprintf(szPath_Xml, "%s\\result\\result.xml", szPath);
pDoc_ado->save(szPath_Xml);


上記のコードで上手くいきました。
ありがとうございました。
Vacant-Eyes
ベテラン
会議室デビュー日: 2004/08/15
投稿数: 97
投稿日時: 2005-09-16 20:59
うまくいってよかったですね!(^o^)/
koara
ベテラン
会議室デビュー日: 2005/09/16
投稿数: 96
投稿日時: 2005-09-20 08:27
ありがとうございます、おかげで解決できました。

本当のところ出来てしまったという感じで
IXMLDOMNodeListPtrの要素を一旦
IXMLDOMElementPtrに格納してから
IXMLDOMDocumentFragmentPtr にappenChildして..
という流れが冗長な感じがします。
こういうものだと思えればいいのですが、
理屈が分からないとどうも釈然としません。

参考になるWEBページ等ありましたら教えて頂けませんでしょうか?
Vacant-Eyes
ベテラン
会議室デビュー日: 2004/08/15
投稿数: 97
投稿日時: 2005-09-20 13:15
引用:

koaraさんの書き込み (2005-09-20 08:27) より:
IXMLDOMNodeListPtrの要素を一旦
IXMLDOMElementPtrに格納してから
IXMLDOMDocumentFragmentPtr にappenChildして..
という流れが冗長な感じがします。


そうですよね。もっとスマートにできてもいいような気がします。

引用:

参考になるWEBページ等ありましたら教えて頂けませんでしょうか?


DOMについて解説しておられるページは探すと結構ありますよ。
個人的には(これは書籍ですが)これがお勧めです。

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