MSXML2:如何使用XPATH更新(+插入和删除)节点



我需要帮助更新XML文件的特定节点。我使用的是MSXML2.DOMDocument60。下面的代码演示了这个想法:

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:1test.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:1final.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

这是我在示例中使用的文件test.xml。它是实际文件的简化版本:

<?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>

编辑:下面是这个答案的代码但我不明白修改xmlRoot会如何影响xmlDoc-是通过ref吗?(见代码中的注释)

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

我觉得答案就在我眼前,但我看不见它

简单xml文件:

<?xml version="1.0"?>
<!-- This file represents a fragment of a bookstore inventory database -->
<bookstore specialty="novel">
<book>
<Title>Beginning XML</Title>
<Publisher>Wrox</Publisher>
</book>
<book>
<Title>Professional XML</Title>
<Publisher>Wrox</Publisher>
</book>
<book>
<Title>Programming ADO</Title>
<author>
<first-name>Mary</first-name>
<last-name>Jones</last-name>      
</author>
<datePublished>1/1/2000</datePublished>
<Publisher>Microsoft Press</Publisher>
</book>
</bookstore>

以下对我编辑单个节点有效。

Dim oDoc As MSXML2.DOMDocument60, sNode As MSXML2.IXMLDOMNode
Set oDoc = New MSXML2.DOMDocument60
oDoc.Load "pathfilename"
Set sNode = oDoc.SelectSingleNode("//book[3]/Title") 'selection criteria using XPath syntax
sNode.Text = "something"
oDoc.Save("pathfilename") 'If same pathfilename is used, it will overwrite.

整个问题是我认为oDocsNode对象是相互独立的。我没有意识到sNode是对oDoc节点的活动引用。多亏了6月7日的答案,我明白了它是如何工作的,然后只花了一点时间就找到了我最初想到的所有3个问题的答案:

Sub UpdateXML()
'Load the XML file into oDoc
Dim oDoc As MSXML2.DOMDocument60
Set oDoc = New MSXML2.DOMDocument60
If Not oDoc.Load("C:1test.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         'Reference to oDoc node
Set sNode = oDoc.selectSingleNode(xPath)
If Not sNode Is Nothing Then     'If node is found then

Dim nTech As IXMLDOMNode
Set nTech = getTechnologies  'Get node from function

'To update selected node
sNode.parentNode.replaceChild nTech, sNode

'To remove node (Reference to sNode must be set again after replaceChild method)
Set sNode = oDoc.selectSingleNode(xPath)
sNode.parentNode.removeChild sNode

'To insert new node into a particular node
xPath = "/root/devices/device[@name='DB']/package[@name='DIL8']"
Set sNode = oDoc.selectSingleNode(xPath)
sNode.appendChild nTech
End If
'Save modified data into new file
oDoc.Save "C:1final.xml"
End Sub

最新更新