创建带编号的XML节点,在创建XML节点时设置属性。

huangapple go评论94阅读模式
英文:

Create numbered XML nodes, set attributes when creating XML node

问题

我有一个Excel宏,从一个文件中读取XML值,并在第二个文件中复制它们。我不能只是复制文件,因为第二个文件有更多和不同的内容,用户输入确定了映射的内容。例如,以电影数据库的示例来说,用户选择要从源到目标复制哪些流派。我需要映射特定的值;源和目标的XPath在一个电子表格中。新的XML文件中并不是所有的标签都存在,所以它们需要在它们的值可以被填充之前由我的代码创建。

我从Greg-R的工作中有了一个很好的开始,链接是https://stackoverflow.com/questions/12149941/create-xml-file-based-on-xpath-from-excel-with-vba;但他的代码不能处理带编号的节点。我从目标标签中去掉了编号,但无法弄清楚如何在节点上添加属性。例如,XPath可以是 //Movies/Title[@number=1]/Actor[@number=5].Name

  1. Sub makeXPath(xmldoc As Object, xpath As String)
  2. '来自:https://stackoverflow.com/questions/12149941/create-xml-file-based-on-xpath-from-excel-with-vba 的原始代码
  3. Dim partsOfPath() As String
  4. Dim oNodeList As IXMLDOMNodeList
  5. Dim strXPathQuery As String
  6. Dim sParent As String
  7. Dim objRootElem As IXMLDOMElement
  8. Dim objMemberElem As IXMLDOMElement
  9. Dim objMemberName As IXMLDOMElement
  10. Dim objParent As Object
  11. Set objParent = xmldoc
  12. partsOfPath = Split(xpath, "/")
  13. For i = LBound(partsOfPath) To UBound(partsOfPath)
  14. If strXPathQuery > "" Then strXPathQuery = strXPathQuery & "/"
  15. strXPathQuery = strXPathQuery & partsOfPath(i)
  16. Set oNodeList = xmldoc.SelectNodes(strXPathQuery)
  17. If oNodeList.Length = 0 Then
  18. '如果我没有这个节点,就创建它
  19. Debug.Print "partsOfPath(" & i & ") = " & partsOfPath(i)
  20. NumberPos = InStr(partsOfPath(i), "[@number=")
  21. If NumberPos > 0 Then
  22. '带编号的节点,提取编号
  23. ElementName = Left(partsOfPath(i), NumberPos - 1)
  24. 'Len("[@number=") = 9。通过不每次计算它来加速代码。每一点都有帮助!
  25. NodeNumber = Mid(partsOfPath(i), NumberPos + 9, Len(partsOfPath(i)) - NumberPos - 9)
  26. Else
  27. ElementName = partsOfPath(i)
  28. NodeNumber = ""
  29. End If
  30. Set objMemberElem = xmldoc.createElement(ElementName)
  31. objParent.appendChild objMemberElem
  32. If Not NodeNumber = "" Then
  33. objMemberElem.createAttribute ("number") '<<<------ 这部分引发错误 :(
  34. .createAttribute ("number")
  35. objParent.Attributes.setNamedItem(objAttr).Text = NodeNumber
  36. End If
  37. '为路径的下一个元素设置父节点
  38. Set objParent = objMemberElem
  39. Else
  40. '将父节点设置为第一次迭代,直到我以后做出其他调整
  41. Set objParent = oNodeList.Item(0)
  42. End If
  43. Next
  44. End Sub

我研究了这个问题(Chrome能处理多少个标签页?)并尝试了各种方法。我应该使用哪些方法?

英文:

I've got an Excel macro reading XML values from one file and replicating them in a second. I can't just copy files, as the second file has more and different stuff, and user input determines what is mapped.
E.g. to use the example of a movie database, the user picks which genres to copy from source to target. I need to map specific values; the XPaths of the source and target are in a spreadsheet. Not all of the tags exist in the new XML file, so they need to be created by my code before their values can be populated.

I've a great start from Greg-R's work at https://stackoverflow.com/questions/12149941/create-xml-file-based-on-xpath-from-excel-with-vba; but his code doesn't handle numbered nodes. I stripped the number from the target tag, but can't figure out the methods for adding the attribute to the node.
E.g. the XPath could be //Movies/Title[@number=1]/Actor[@number=5].Name

  1. Sub makeXPath(xmldoc As Object, xpath As String)
  2. 'Original code from: https://stackoverflow.com/questions/12149941/create-xml-file-based-on-xpath-from-excel-with-vba
  3. Dim partsOfPath() As String
  4. Dim oNodeList As IXMLDOMNodeList
  5. Dim strXPathQuery As String
  6. Dim sParent As String
  7. Dim objRootElem As IXMLDOMElement
  8. Dim objMemberElem As IXMLDOMElement
  9. Dim objMemberName As IXMLDOMElement
  10. Dim objParent As Object
  11. Set objParent = xmldoc
  12. partsOfPath = Split(xpath, "/")
  13. For i = LBound(partsOfPath) To UBound(partsOfPath)
  14. If strXPathQuery > "" Then strXPathQuery = strXPathQuery & "/"
  15. strXPathQuery = strXPathQuery & partsOfPath(i)
  16. Set oNodeList = xmldoc.SelectNodes(strXPathQuery)
  17. If oNodeList.Length = 0 Then
  18. 'if I don't have the node, create it
  19. Debug.Print "partsOfPath(" & i & ") = " & partsOfPath(i)
  20. NumberPos = InStr(partsOfPath(i), "[@number=")
  21. If NumberPos > 0 Then
  22. 'Numbered node, extract the number
  23. ElementName = Left(partsOfPath(i), NumberPos - 1)
  24. 'Len("[@number=") = 9. Speed the code up by not calculating it each time. Every little bit helps!
  25. NodeNumber = Mid(partsOfPath(i), NumberPos + 9, Len(partsOfPath(i)) - NumberPos - 9)
  26. Else
  27. ElementName = partsOfPath(i)
  28. NodeNumber = ""
  29. End If
  30. Set objMemberElem = xmldoc.createElement(ElementName)
  31. objParent.appendChild objMemberElem
  32. If Not NodeNumber = "" Then
  33. objMemberElem.createAttribute ("number") '<<<------ This bit is throwing errors :(
  34. .createAttribute ("number")
  35. objParent.Attributes.setNamedItem(objAttr).Text = NodeNumber
  36. End If
  37. 'setting the parent for the next element of the path
  38. Set objParent = objMemberElem
  39. Else
  40. 'setting parent to first iteration, until I make adjustment otherwise later
  41. Set objParent = oNodeList.Item(0)
  42. End If
  43. Next
  44. End Sub

I researched this (How many tabs can Chrome handle?) and tried various methods. What are the methods I should be using?

答案1

得分: 1

createElement类似,createAttribute是XML文档的方法,而不是节点,比如objMemberElem

这应该有效:

  1. If Not NodeNumber = "" Then
  2. Set objAttr = xmldoc.createAttribute("number")
  3. objAttr.Value = NodeNumber
  4. objMemberElem.Attributes.setNamedItem objAttr
  5. End If
英文:

Just like createElement, createAttribute is a method of the xml document, not of a node like objMemberElem.

This should work:

  1. If Not NodeNumber = "" Then
  2. Set objAttr = xmldoc.createAttribute("number")
  3. objAttr.Value = NodeNumber
  4. objMemberElem.Attributes.setNamedItem objAttr
  5. End If

huangapple
  • 本文由 发表于 2023年2月19日 05:22:57
  • 转载请务必保留本文链接:https://go.coder-hub.com/75496479.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定