VBAでXMLの要素を追加するときの処理方法

解決


CDJSATORU  2009-03-18 19:51:18  No: 101610  IP: 192.*.*.*

いつも勉強させていただいています。
ありがとうございます。

Excel2007上のVBAで下記のようなXML処理を行いたいのですが、
求める結果と違う処理がされてしまいます。

何卒、ご指導をお願いできませんでしょうか・・・?


■やりたいこと(処理前)

<?xml version="1.0" encoding="UTF-8" ?>
<タグ1 属性11="abc" 属性12="w">
    <タグ2>
        <タグ3 属性31="1">
            <タグ5 属性51="abc"/> '←[タグ5]の[属性51]が[1000]だったら追加処理
            <タグ5 属性52="def"/>
        </タグ3>
        <タグ4 属性41="2">
            <タグ5 属性51="1000"/> '←[タグ5]の[属性51]が[1000]だったら追加処理
            <タグ5 属性52="1100"/>
        </タグ4>
    </タグ2>
</タグ1>

    ↓

■やりたいこと(処理後)
<?xml version="1.0" encoding="UTF-8" ?>
<タグ1 属性11="abc" 属性12="w">
    <タグ2>
        <タグ3 属性31="1">
            <タグ5 属性51="abc"/>  '←[タグ5]の[属性51]が[1000]だったら追加処理
            <タグ5 属性52="def"/>
        </タグ3>
        <タグ4 属性41="2">
            <タグ5 属性51="1000"/>   '←[タグ5]の[属性51]が[1000]だったら追加処理
            <タグ5 属性52="1100"/>
      <タグ6 属性61="abcdef"/> '←ここに追加したい
        </タグ4>
    </タグ2>
</タグ1>


■求める結果と違う処理
Sub Macro1

Dim DomXmlDocument As MSXML2.DOMDocument
Set DomXmlDocument = New MSXML2.DOMDocument

DomXmlDocument.Load("test.xml")

Dim namedNodeMap As IXMLDOMNamedNodeMap
Dim MyNode As IXMLDOMNode

For Each Node In DomXmlDocument.SelectNodes("//タグ5/@*")
    If Node.NodeValue = "1000" Then
        Set MyNode = DomXmlDocument.createNode(2, "属性61", "abcdef")
        Set namedNodeMap = DomXmlDocument.DocumentElement.ChildNodes.Item(4).Attributes
        namedNodeMap.setNamedItem MyNode
    End If
Next

DomXmlDocument.Save ("test_after.xml")

End Sub

編集 削除
魔界の仮面弁士  2009-03-19 01:01:29  No: 101611  IP: 192.*.*.*

> <タグ5 属性51="abc"/> '←[タグ5]の[属性51]が[1000]だったら追加処理

コメントの意図ならば、「'」よりも「<!--  -->」の方が良いかも。
本題とは無関係ですけれども。


> Set MyNode = DomXmlDocument.createNode(2, "属性61", "abcdef")
第3引数に属性値を指定しているようですが、そこにくるのは名前空間の指定ですよ。
また、「2」のようなマジックナンバーではなく、「NODE_ATTRIBUTE」などの定数を使うようにしましょう。

それと、肝心の「<タグ6>」の要素ノードを作るためのコードも抜け落ちているようです。


> Set namedNodeMap = DomXmlDocument.DocumentElement.ChildNodes.Item(4).Attributes

これはエラーになりますね。

load 前の preserveWhiteSpace プロパティの値にもよりますが、
preserveWhiteSpace = False で読み込んでいたとしたら、
『DomXmlDocument.DocumentElement.ChildNodes』の .length は 1 ですよね。
タグ2ノードしか返さないはずなので、.Item(4) はエラーです。

preserveWhiteSpace = True であったとしても、.lengh は 3 です。
「タグ1 と タグ2 の間のテキストノード」と、「タグ2 の要素ノード」と
「タグ2 の終わりからタグ1 の間のテキストノード」だけであって、
『4』は存在しません。



> ■やりたいこと(処理後)
私が書くとしたら、こうかな…。

Dim DomXmlDocument As MSXML2.DOMDocument
Set DomXmlDocument = New MSXML2.DOMDocument

DomXmlDocument.async = False
DomXmlDocument.preserveWhiteSpace = True
DomXmlDocument.Load "test.xml"

DomXmlDocument.setProperty "SelectionLanguage", "XPath"
Dim Node As IXMLDOMNode
For Each Node In DomXmlDocument.selectNodes("//*[タグ5/@属性51='1000']")
    Node.insertBefore(DomXmlDocument.createElement("タグ6"), Nothing).Attributes.setNamedItem(DomXmlDocument.createAttribute("属性61")).nodeValue = "abcdef"
Next

DomXmlDocument.save "test_after.xml"

編集 削除
CDJSATORU  2009-03-19 11:02:25  No: 101612  IP: 192.*.*.*

迅速かつ確実そして懇切丁寧な回答をありがとうございます。

意図した動作が確認できました!

編集 削除