MSXML2:如何使用 XPATH 更新(+插入和删除)节点
MSXML2: How to update (+insert and delete) node using 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:\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:\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
这是我在示例中使用的文件 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>
编辑:下面是 this answer 的代码,但我不明白修改 xmlRoot
会如何影响 xmlDoc
-是参考文献吗? (见代码中的注释)
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 "path\filename"
Set sNode = oDoc.SelectSingleNode("//book[3]/Title") 'selection criteria using XPath syntax
sNode.Text = "something"
oDoc.Save("path\filename") 'If same path\filename is used, it will overwrite.
整个问题是我认为 oDoc
和 sNode
对象是相互独立的。我没有意识到 sNode
是对 oDoc
节点的主动引用。感谢 June7 的回答,我了解了它是如何工作的,然后只花了一点时间就找到了我最初想到的所有 3 个问题的答案:
Sub UpdateXML()
'Load the XML file into oDoc
Dim oDoc As MSXML2.DOMDocument60
Set oDoc = New MSXML2.DOMDocument60
If Not oDoc.Load("C:\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 '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:\final.xml"
End Sub
我需要帮助更新 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:\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:\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
这是我在示例中使用的文件 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>
编辑:下面是 this answer 的代码,但我不明白修改 xmlRoot
会如何影响 xmlDoc
-是参考文献吗? (见代码中的注释)
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 "path\filename"
Set sNode = oDoc.SelectSingleNode("//book[3]/Title") 'selection criteria using XPath syntax
sNode.Text = "something"
oDoc.Save("path\filename") 'If same path\filename is used, it will overwrite.
整个问题是我认为 oDoc
和 sNode
对象是相互独立的。我没有意识到 sNode
是对 oDoc
节点的主动引用。感谢 June7 的回答,我了解了它是如何工作的,然后只花了一点时间就找到了我最初想到的所有 3 个问题的答案:
Sub UpdateXML()
'Load the XML file into oDoc
Dim oDoc As MSXML2.DOMDocument60
Set oDoc = New MSXML2.DOMDocument60
If Not oDoc.Load("C:\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 '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:\final.xml"
End Sub