[リストへもどる]   [VBレスキュー(花ちゃん)]
一括表示

投稿時間:2006/03/04(Sat) 01:05
投稿者名:cum
Eメール:
URL :
タイトル:
VB6:msxml3 removeChildで複数のノード削除
初めまして。VB始めて3ヶ月のcumと申します。
今VB6でXMLを読み込み、指定したデータ(複数)を消すモジュールを
作成しています。removeChildを使用して
ひとつのノードを消す事はできたのですが、
立て続けに2つノードを消そうとすると、
二つめを消す時にエラーがでてしまい困っています。

サンプルを以下のような感じで作っています。
消したいデータはid="1",id="2"です

★★C:\test.xml★★
<?xml version="1.0" encoding="UTF-8"?>
<List>
    <test id="1">test1</test>
    <test id="2">test2</test>
    <test id="3">test3</test>
</List>


★★VB★★
Dim domData As DOMDocument30
Dim nodeData As IXMLDOMNode

Set nodeData = New DOMDocument30

'C:\test.xmlのデータ読み込み
domData.Load("C:\test.xml")

Set nodeData= domData.documentElement()

'↓removeChildを使用してid=1,id=2を削除したい
Set nodeData=nodeData.removeChild(nodeData.childNodes(0))
Set nodeData=nodeData.removeChild(nodeData.childNodes(1))
'↑一つ目消去前にあったnodeData.childNodes(1)は
'二つ目を消す時Nothingの状態になる。

’データを保存
domData.save("C:\test.xml")

初心者ゆえ見苦しいコードかもしれませんが
どうぞ宜しくお願い致します。

投稿時間:2006/03/06(Mon) 03:44
投稿者名:魔界の仮面弁士
Eメール:
URL :
タイトル:
Re: VB6:msxml3 removeChildで複数のノード削除
ならば、以下のいずれかになりますよね。(MSXML6 のコードですが、MSXML3 でも同様でしょう)

'------------------
Set domData = New DOMDocument60
domData.Load "C:\test.xml"
Set nodeData = domData.documentElement
nodeData.removeChild nodeData.childNodes(0)  'id=1
nodeData.removeChild nodeData.childNodes(0)  'id=2
domData.save "C:\test.xml"
'------------------
Set domData = New DOMDocument60
domData.Load "C:\test.xml"
Set nodeData = domData.documentElement
nodeData.removeChild nodeData.childNodes(1)  'id=2
nodeData.removeChild nodeData.childNodes(0)  'id=1
domData.save "C:\test.xml"
'------------------


> 二つめを消す時にエラーがでてしまい困っています。
では、元のコードを追って見ましょうか。

そもそも、問題点は 2 つあります。
『nodeData 変数を使い回している』という点と、
『0番のノードを削除したあと、1番を削除している』という点です。

削除すればその分、インデックスもずれるという事に注意してください。


> Set nodeData = New DOMDocument30
> domData.Load("C:\test.xml")
えぇと。New する相手は domData ですよね? (^^;
そうしないと、domData の中身が Nothing のままですから…。


> Set nodeData= domData.documentElement()
この時点で、
domData =「<?xml version="1.0"?><List><test id="1">test1</test><test id="2">test2</test><test id="3">test3</test></List>」
nodeData =「<List><test id="1">test1</test><test id="2">test2</test><test id="3">test3</test></List>」
ですね。ここまでは 問題無かったのですが…次の行以降がマズイです。


> Set nodeData=nodeData.removeChild(nodeData.childNodes(0))
まず、ここで一つ目の問題があります。nodeData 変数の扱いです。

実行前の段階では、nodeData は List タグの内容を保持しており、
nodeData.childNodes(0) は「<test id="1">test1</test>」を指していますよね。

しかしながら、removeChild メソッドは、「削除されたノード」への参照を返すわけですから、
この行の実行により、nodeData の中身が「<test id="1">test1</test>」に変更されてしまいます。
すなわち、この行を実行すると、その結果はこうなります。
domData …… 「<?xml version="1.0"?><List><test id="2">test2</test><test id="3">test3</test></List>」
nodeData …… 「<test id="1">test1</test>」


> Set nodeData=nodeData.removeChild(nodeData.childNodes(1))
さて、nodeData が変更されてしまった事により、この行の実行結果に影響が出てきます。

この行を実行する時点で、nodeData = 「<test id="1">test1</test>」であったわけですから、
nodeData.childNodes(0) = 「test1」
nodeData.childNodes(1) は Nothing
となるわけです。
nodeData 変数の参照先を変更した事により、このような問題が生じたわけですね。


しかしながら、nodeData 変数の参照先を書き変えていなかったとしても、
もう一つの問題があります。先の removeChild により、id=1 は削除されていて
nodeData ……「<List><test id="2">test2</test><test id="3">test3</test></List>」
だけとなっているわけですから、その分、インデックスも一つずれて、
nodeData.childNodes(1) …「<test id="3">test3</test>」
を指す事になります。id=2 を指したいなら、インデックスは 0 ですよね。

投稿時間:2006/03/06(Mon) 23:10
投稿者名:cum
Eメール:
URL :
タイトル:
解決しました!
魔界の仮面弁士様
サンプルに加え、とても丁寧かつ分かりやすい解説有難うございます!
自分がいかにものの動きを追っていなかったかと
言う事を痛感しました・・・。
ウォッチウィンドウをもっとうまく活用して
しっかり中身を理解しながらモノを作っていく
事を心がけようと思います。
有難うございました!