プロが教えるわが家の防犯対策術!

MSXML3.0で
IXMLDOMDocumentPtr pXMLDOMDoc;
pXMLDOMDoc.CreateInstance(__uuidof(DOMDocument));
pXMLDOMDoc->put_async(VARIANT_FALSE);
pXMLDOMDoc->validateOnParse = FALSE;
pXMLDOMDoc->load( _variant_t("XMLドキュメントのパス") );

としてXMLドキュメントを読み込み、属性が一致したノードを削除したいです。

例:xml
<root>
<category name='1'>
<item>

</item>
</category>
<category name='1'>
<item>
バイク
</item>
</category>
<category name='2'>
<item>
自転車
</item>
</category>
<category name='2'>
<item>
徒歩
</item>
</category>
</root>

上記のxmlからcategoryのname属性が1のものを削除し
下記のように変換したいです。

<root>
<category name='2'>
<item>
自転車
</item>
</category>
<category name='2'>
<item>
徒歩
</item>
</category>
</root>

A 回答 (4件)

>removeAllメソッドがありませんでした


そんなことはないはずです。
以下のMSのサイトでMSXML3以降で(C/C++で)使えると書いてあります。
http://msdn.microsoft.com/library/default.asp?ur …
参考URLによると

Applies to
IXMLDOMSelection

と書いてありますから
IXMLDOMSelection
を使う必要があります。(メンバーにremoveAllがあります)
selectNodesからIXMLDOMSelectionをセットするサンプルが以下にあります
http://msdn.microsoft.com/library/default.asp?ur …

この回答への補足

自分ではMSXML3を使用しているつもりでしたが、実は
#import "C:\Program Files\Common Files\System\ADO\msado15.dll" rename_namespace("MSXML") rename("EOF", "EndOfFile")
#import "msxml.dll"
using namespace MSXML;
としておりMSXML2.0を使用していたようです。

そこで
#import "C:\Program Files\Common Files\System\ADO\msado15.dll" rename_namespace("MSXML2") rename("EOF", "EndOfFile")
#import "msxml3.dll"
using namespace MSXML2;
としたのですが

IXMLDOMSelection pXMLDOMSel;
と定義すると

プロジェクトのパス\ファイル名\ファイル名.cpp((211) : error C2259: 'IXMLDOMSelection' : 抽象クラスあるいは構造体のオブジェクトが宣言されています。

というエラーと

プロジェクトのパス\ファイル名\ファイル名.cpp(211) : warning C4259: 'long __stdcall IDispatch::GetTypeInfoCount(unsigned int *)' : 純粋仮想関数は定義されていません。
c:\program files\microsoft visual studio\vc98\include\oaidl.h(2697) : 'GetTypeInfoCount' の宣言を確認してください。
プロジェクトのパス\ファイル名\ファイル名.cpp(211) : warning C4259: 'long __stdcall IDispatch::GetTypeInfo(unsigned int,unsigned long,struct ITypeInfo ** )' : 純粋仮想関数は定義されていません。
c:\program files\microsoft visual studio\vc98\include\oaidl.h(2700) : 'GetTypeInfo' の宣言を確認してください。
プロジェクトのパス\ファイル名\ファイル名.cpp(211) : warning C4259: 'long __stdcall IDispatch::GetIDsOfNames(const struct _GUID &,unsigned short ** ,unsigned int,unsigned long,long *)' : 純粋仮想関数は定義されていません。
c:\program files\microsoft visual studio\vc98\include\oaidl.h(2705) : 'GetIDsOfNames' の宣言を確認してください。
プロジェクトのパス\ファイル名\ファイル名.cpp(211) : warning C4259: 'long __stdcall IDispatch::Invoke(long,const struct _GUID &,unsigned long,unsigned short,struct tagDISPPARAMS *,struct tagVARIANT *,struct tagEXCEPINFO *,unsigned int *)' : 純粋仮想関
数は定義されていません。

または

プロジェクトのパス\ファイル名.cpp(211) : warning C4259: 'long __stdcall MSXML2::IXMLDOMNodeList::raw_reset(void)' : 純粋仮想関数は定義されていません。
プロジェクトのパス\ファイル名\debug\msxml3.tlh(588) : 'raw_reset' の宣言を確認してください。
プロジェクトのパス\ファイル名\ファイル名.cpp(211) : warning C4259: 'long __stdcall MSXML2::IXMLDOMNodeList::get__newEnum(struct IUnknown ** )' : 純粋仮想関数は定義されていません。
プロジェクトのパス\ファイル名\debug\msxml3.tlh(589) : 'get__newEnum' の宣言を確認してください。
プロジェクトのパス\ファイル名\ファイル名.cpp(211) : warning C4259: 'long __stdcall MSXML2::IXMLDOMSelection::get_expr(unsigned short ** )' : 純粋仮想関数は定義されていません。
プロジェクトのパス\ファイル名\debug\msxml3.tlh(4151) : 'get_expr' の宣言を確認してください。

という警告が連発してしまいます。
何が原因なのでしょうか?

補足日時:2005/09/14 11:00
    • good
    • 0
この回答へのお礼

BLUEPIXYさんにはお世話になりっぱなしです。
感謝してます。

BLUEPIXYさんへは無理でも僕の知ってることで助かる人もいると思うので見習ってレスを入れようと思いました。

連結の方はxsl関数のdocument()を使い出来ました。
そこで削除は<xsl:script>でやろうと考え直していたのですが、
どうやら名前空間
http://www.w3.org/TR/WD-xsl
が<xsl:output>等と干渉するらしく
削除はやはりDOMを使うしかないと思っていた矢先でした。

MSDNは昨日調べたのですが、XMLまで辿り着いてMSXML4.0以外の所を探していてReferenceを見つけることが出来ませんでした。
MSDNはもう少し入りやすければいいのですが、慣れるしかないのでしょうね(苦笑

早速試してみます!

お礼日時:2005/09/14 09:11

>警告が連発してしまいます。


実際に試していないのでなんですが
http://www.utj.co.jp/xml/dev/dom/dxdom1_1.html
http://www.utj.co.jp/xml/dev/dom/dxdom2_1.html
が参考になるような気がします

この回答への補足

レスを付ける場所を間違えてしまいました。

ありがとうございます、一応自己解決しました。
IXMLDOMSelection *pIXMLDOMSelection=NULL;
と宣言することでエラー、警告ともでなくなりました。

c2259というエラーコードをgoogleで検索すると
オーバーライドと純粋関数というキーワードに突き当たりました。
上記の書き方との繋がりがいまいちつかめてないので、
もう少し調べてみたいと思います。

上記のサイト勉強になりました。
defaultではXSLPatternとなっているのですね。
それとIXMLDOMDocument2でないとXPathが使えない
ほんと勉強になります。

補足日時:2005/09/14 12:35
    • good
    • 0

こんにちは、ちょっと反則なんですが、


http://okweb.jp/kotaeru.php3?q=1637728
がもう締め切られちゃったので、こっちに書きます。
今日、ウロウロしてたら、原因と対策を思いつきました。
それは…
<xsl:text>-</xsl:text>
<xsl:text>,</xsl:text>
のように、地の部分に書き込むんじゃなくて、xsl:textエレメントを使うということです。
最初のvalue-of以降の地の部分に書き込みがあるので、以降の改行とかタブがそのまま使われるのだと思います。
っていうかもう試してみましたがうまくいきます!

この回答への補足

上記の件解決しました。
IXMLDOMSelection *pIXMLDOMSelection=NULL;
サンプルを真似したら出来ました、調べていくとオーバーライドと純粋仮想関数というキーワードに行き当たりました。 今から勉強してみます。

補足日時:2005/09/14 12:31
    • good
    • 0
この回答へのお礼

出来ました、こんな親切にして頂けるなんて感激です。
言葉でありがとうございますと伝えたいです。

地の部分に文字が書いてあるのを認識して
改行等が有効になっていたのですね。

タブ、スペース、改行すべて無視してくれるようになりました。
ありがとうございました。

お礼日時:2005/09/14 08:45

setProperty("SelectionLanguage", "XPath");


して
selectNodes("//category[@name='1']");
して
removeAll();
すればいいです。
*
Jscriptでのサンプル
var xmlDoc = new ActiveXObject("Msxml2.DOMDocument.3.0");
var selectNodes;
xmlDoc.setProperty("SelectionLanguage", "XPath");
xmlDoc.async = false;
xmlDoc.load("move.xml");
if (xmlDoc.parseError.errorCode != 0) {
var myErr = xmlDoc.parseError;
WScript.Echo("error:" + myErr.reason);
} else {
selectNodes = xmlDoc.selectNodes("//category[@name='1']");
selectNodes.removeAll();
xmlDoc.save("out.xml");
}
色々面倒くさいのでCでのサンプルではないですが、やることはほぼ同じだと思います。

この回答への補足

その後C++で試行錯誤したのですが、

selectNodes = xmlDoc.selectNodes("//category[@name='1']");
は出来たのですが、removeAllメソッドがありませんでした
ので以下のように変えたのですが駄目でした。

IXMLDOMNodePtr pXmlNode;
IXMLDOMNodeListPtr pXmlNodeList;
long lNum = 0;

pNodeList = pXMLDOMDoc->selectNodes("//category[@name='1']");
pNodeList->get_length(&lNum);

for(long lCount= 0; lCount < lNum; lCount++){
pNodeList->get_item(lCount, &pXmlNode);
pXMLDOMDoc->removeChild(pXmlNode);
}
pXMLDOMDoc->save(xmlの保存先のパス);

やりたいことは、DB上の在庫データ(正確には少し違うのですが)を毎日XMLドキュメントとして保管し
1昨日分のデータと本日分のデータを結合して1つのXMLドキュメントにします。

1日分のデータは前1日分のデータを持っているので、
結合の際に前1日分のデータにして出力します。
[例]
前日分のデータ(9/11, 9/12)
本日分のデータ(9/12, 9/13)

必要なデータは
前日分のデータ(9/12)+本日分のデータ(9/12, 9/13)
を結合します。

結合しておいてXSLで省く(こちらはやった事があります)という様に方向転換しようかと思うのですが、
A:
<root>
<move>
<category name='2'>
<item>
自転車
</item>
</category>
<category name='2'>
<item>
徒歩
</item>
</category>
</move>
</root>
B:
<root>
<move>
<category name='1'>
<item>

</item>
</category>
<category name='1'>
<item>
バイク
</item>
</category>
</move>
</root>
を結合するにはどうしたらよいのでしょうか?
できればCでの情報が少なくて困ってるので、Cの情報を希望します。

補足日時:2005/09/13 14:13
    • good
    • 0
この回答へのお礼

ありがとうございます。

参考にさせて頂き早速やってみます。

せっかく教えて頂いたので、他の方のためにもCで完成させて、ソースを掲載させてから締切りさせて頂きたいと思います。

大変参考になりました。

お礼日時:2005/09/12 09:00

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!