VBA创建带编号属性的XML节点问题求助
解决VBA XML处理带属性编号节点的问题
1. 正确解析带属性的XPath结构
首先要把带属性的XPath拆分成节点层级和对应属性条件,比如你提到的//Movies/Title[@number=1]/Actor[@number=5].Name,可拆分为:
- 根级节点:Movies
- 子节点:Title,属性
number="1" - 子节点:Actor,属性
number="5" - 最终目标节点:Name
你已经提取了编号,接下来需要把每个节点的属性键值对分离,比如从Title[@number=1]中提取属性名number和属性值1。
2. 递归创建/定位带属性的节点
VBA的XML DOM(MSXML)没有直接根据带属性的XPath创建节点的方法,需要手动逐层检查:节点存在则定位,不存在则创建,同时为节点添加属性。
以下是核心递归函数:
' 递归定位或创建带属性的XML节点 Function GetOrCreateNode(parentNode As IXMLDOMNode, nodeName As String, attrName As String, attrValue As String) As IXMLDOMNode Dim targetNode As IXMLDOMNode Dim xmlAttr As IXMLDOMAttribute ' 检查父节点下是否存在符合属性条件的子节点 Set targetNode = parentNode.SelectSingleNode(nodeName & "[" & attrName & "='" & attrValue & "']") ' 节点不存在则创建并添加属性 If targetNode Is Nothing Then Set targetNode = parentNode.ownerDocument.createElement(nodeName) ' 创建属性并赋值 Set xmlAttr = parentNode.ownerDocument.createAttribute(attrName) xmlAttr.Value = attrValue targetNode.Attributes.setNamedItem xmlAttr parentNode.appendChild targetNode End If Set GetOrCreateNode = targetNode End Function
3. 完整流程示例(从源XML读取并写入目标XML)
假设你已从Excel中获取源XPath、目标XPath及对应属性信息,以下是完整处理逻辑:
Sub TransferXMLValues() Dim srcDoc As New MSXML2.DOMDocument60 Dim destDoc As New MSXML2.DOMDocument60 Dim srcXPath As String Dim currentDestNode As IXMLDOMNode Dim nameNode As IXMLDOMNode ' 加载源和目标XML文件 srcDoc.Load "C:\Source.xml" destDoc.Load "C:\Target.xml" destDoc.async = False destDoc.validateOnParse = False ' 初始化目标根节点,不存在则创建 Set currentDestNode = destDoc.SelectSingleNode("//Movies") If currentDestNode Is Nothing Then Set currentDestNode = destDoc.createElement("Movies") destDoc.appendChild currentDestNode End If ' 创建Title节点(带number=1属性) Set currentDestNode = GetOrCreateNode(currentDestNode, "Title", "number", "1") ' 创建Actor节点(带number=5属性) Set currentDestNode = GetOrCreateNode(currentDestNode, "Actor", "number", "5") ' 创建或定位Name节点 Set nameNode = currentDestNode.SelectSingleNode("Name") If nameNode Is Nothing Then Set nameNode = destDoc.createElement("Name") currentDestNode.appendChild nameNode End If ' 从源XML读取值并写入目标节点 srcXPath = "//SourceMovies/SourceTitle[@number=1]/SourceActor[@number=5].Name" ' 示例源XPath nameNode.Text = srcDoc.SelectSingleNode(srcXPath).Text ' 保存修改后的目标XML destDoc.Save "C:\Target_Updated.xml" End Sub
4. 常见报错的解决要点
- 添加属性出错:必须用
createAttribute创建属性对象,再通过setNamedItem添加到节点,禁止直接给Attributes赋值(比如错误写法:targetNode.Attributes("number") = "1")。 - XPath查询失败:XPath中字符串类型属性必须加单/双引号,比如
[@number=1]要写成[@number='1'],避免类型匹配问题。 - DOM版本问题:使用
MSXML2.DOMDocument60高版本对象,旧版本对XPath 1.0的支持存在缺陷。
内容的提问来源于stack exchange,提问作者Scott
相关产品推荐
相关产品推荐

