I need help with updating a particular node of the XML file. I use the MSXML2.DOMDocument60. This code demonstrates the idea:
Option Explicit
Sub UpdateXML()
'Load the XML file into oDoc
Dim oDoc As MSXML2.DOMDocument60
Set oDoc = New MSXML2.DOMDocument60
If Not oDoc.Load("C:\1\test.xml") Then
Debug.Print oDoc.parseError
Exit Sub
End If
Dim xPath As String
'Lets say I want to update this node:
xPath = "/root/devices/device[@name='DB']/package[@name='DIL8']/technologies"
Dim sNode As IXMLDOMNode
'I know how to select it
Set sNode = oDoc.selectSingleNode(xPath)
If Not sNode Is Nothing Then
Debug.Print sNode.XML
'This function returns the node with new data (function follows)
Debug.Print getTechnologies.XML
'Here I need to insert the data returned by getTechnologies()
'into the correct place of the oDoc (specified by xPath)
'this does not work
oDoc.selectSingleNode(xPath) = getTechnologies
'??? odoc.replaceChild ??? I'm lost here
'It would be great to see the example how to insert and delete
'the node <technologies> of the oDoc using xPath... if it is possible of course.
End If
'Save modified data into new file
oDoc.Save "C:\1\final.xml"
'Final file should now contain "newValue" within the
'/root/devices/device[@name='DB']/package[@name='DIL8']/technologies
End Sub
Function getTechnologies() As IXMLDOMNode
'This is just a simplified example to demonstrate the function
'that returns the IXMLDOMNode object
'In real, this function pulls data from a database
Dim oNode As MSXML2.DOMDocument60
Set oNode = New MSXML2.DOMDocument60
Dim sXml As String
sXml = "<technologies>" & vbCrLf & _
" <property name='prop1' value='newValue'/>" & vbCrLf & _
" <property name='prop2' value='newValue'/>" & vbCrLf & _
" <property name='prop3' value='newValue'/>" & vbCrLf & _
" <property name='prop4' value='newValue'/>" & vbCrLf & _
"</technologies>"
If Not oNode.loadXML(sXml) Then
Debug.Print oNode.parseError
Else
Set getTechnologies = oNode.selectSingleNode("/technologies")
End If
End Function
Here's the file test.xml
that I use in my example. It is a simplified version of the real file:
<?xml version="1.0" encoding="UTF-8"?>
<root>
<library>
<items>
<item name="foo"/>
<item name="bar"/>
<item name="foo2"/>
<item name="bar2"/>
</items>
</library>
<devices>
<device name="DB">
<package name="DIL4">
<something>Another tree could be here</something>
<technologies>
<property name="prop1" value="oldValue"/>
<property name="prop2" value="oldValue"/>
<property name="prop3" value="oldValue"/>
<property name="prop4" value="oldValue"/>
</technologies>
</package>
<package name="DIL8">
<technologies>
<property name="prop1" value="oldValue"/>
<property name="prop2" value="oldValue"/>
<property name="prop3" value="oldValue"/>
<property name="prop4" value="oldValue"/>
</technologies>
<something>The order is not guaranteed</something>
</package>
<package name="DIL16">
<technologies>
<property name="prop1" value="oldValue"/>
<property name="prop2" value="oldValue"/>
<property name="prop3" value="oldValue"/>
<property name="prop4" value="oldValue"/>
</technologies>
</package>
</device>
<device name="NPN">
<package name="SOT23">
<technologies>
<property name="prop1" value="oldValue"/>
<property name="prop2" value="oldValue"/>
<property name="prop3" value="oldValue"/>
<property name="prop4" value="oldValue"/>
</technologies>
</package>
</device>
</devices>
</root>
EDIT: Below is the code of this answer but I don't understand how modifying the xmlRoot
can afect the xmlDoc
- is it byRef? (see the notes in the code)
Sub XMLTest()
Dim myVar As String, pathToXML As String
Dim xmlDoc As Object, xmlRoot As Object
Set xmlDoc = CreateObject("MSXML2.DOMDocument")
pathToXML = "N:\example.xml" '<--- change the path
Call xmlDoc.Load(pathToXML)
Set xmlRoot = xmlDoc.getElementsByTagName("RefTest").Item(0)
myVar = "foobar" '<--- your value
'Here the xmlRoot object is updated
xmlRoot.selectSingleNode("iRef5").Text = myVar
'Here the xmlDoc is saved
Call xmlDoc.Save(pathToXML)
End Sub
I feel like the answer is right in front of my eyes, but I can't see it
The whole problem was that I thought that the
oDoc
andsNode
objects were independent of each other. I didn't realize thatsNode
is an active reference to theoDoc
node. Thanks to the June7 answer, I understood how it works and then it only took a moment to find the answer to all 3 questions that I originally had in mind: