将多个xml节点提取到数组中而不进行循环

时间:2013-04-25 10:52:31

标签: xml excel excel-vba xmldom vba

我有一个xml doc,看起来像这样:

<rng>
  <col1>
    <row1>A</row1>
    <row2>B</row2>
    <row3>C</row3>
    <row4>D</row4>
  </col1>
  <col2>
    <row1>E</row1>
    <row2>F</row2>
    <row3>G</row3>
    <row4>H</row4>
  </col2>
</rng>

有一个 lot 更多col节点,每个节点包含几千个行元素。

我想解析行元素中的值,并最终将它们放到电子表格中。我目前正在这样做:

' get a list of the col elements (thi sits in a loop to go through them all)
Set oXMLColNodeList = oXMLDoc.selectNodes("//saveStates/rng/*")

' Lop through each column
For colNum = 1 To oXMLColNodeList.Length
    ' get all the row nodes for that coulmn
    Set oXMLRowNodeList = oXMLDoc.selectNodes("//saveStates/rng"/col" & colNum & "/*")

    ' loop through all the row nodes
    For rowNum = 1 To oXMLRowNodeList.Length
       ' get the node to do something with it 
       Set oXMLNode = oXMLDoc.selectSingleNode("//saveStates/rng/col" & colNum & "/row" & rowNum)


    next rowNum
next colNum

即。我循环遍历col节点,然后遍历每个行节点以获取值A,B,C,D等。当行元素的数量达到数万时,这是灾难性的慢。

我没有太多从XML文档解析的经验,我正在寻找一种方法同时从'row *'节点中提取所有值,而不必循环遍历它们。这可能吗?

2 个答案:

答案 0 :(得分:0)

也许您可以使用 ADO DB Recordset 在Recordset中打开xml DOM文档,然后使用 Range.CopyFromRecordset 方法在添加后将数据转储到Excel中过滤以仅获取您想要的记录?

这是来自MSDN: How to obtain a Recordset from XML

的一些示例代码
Public Function RecordsetFromXMLDocument(XMLDOMDocument As DOMDocument) As Recordset
Dim oRecordset As ADODB.Recordset
dim destRange as range

set destrange=range("B2")

Set oRecordset = New ADODB.Recordset

oRecordset.Open XMLDOMDocument 'pass the DOM Document instance as the Source argument

Set RecordsetFromXMLDocument = oRecordset  'return the recordset

destRange.CopyFromRecordset oRecordset 

Set oRecordset = Nothing

End Function

答案 1 :(得分:0)

@chrisSpaceman, 在这里,您可以找到使用XMLDOM的更短路径。我添加了一些声明以显示一个完整的示例(我假设你知道如何操作数组,所以我把它放在旁边)。

Option Explicit
Sub ReadRows()

'Declarations
Dim oXMLDoc         As Object    ' XML document (object)
'Dim oXMLColNodeList As Object   ' you don't need this list any more ! 
Dim oXMLRowNodeList As Object    ' needed node list
Dim oXMLNode        As Object    ' single node within this list
Dim xPE             As Object    ' ParseError object
Dim strErrText      As String    ' Error message
Dim sFileName       As String    ' user defined file path
' =================================
' 0. User defined File Name <==  !
' =================================
  sFileName = ThisWorkbook.Path & "\data\test.xml"
' =================================
' 1. XML Declaration oXMLDoc
' =================================
' Set oXMLDoc = New MSXML2.DOMDocument60                   ' Early Binding
  Set oXMLDoc = CreateObject("Msxml2.DOMDocument.6.0")     ' Late  Binding

' XPath, Validation
  oXMLDoc.setProperty "SelectionLanguage", "XPath"
  oXMLDoc.validateOnParse = False
' =================================
' 2. Load XML File
' =================================
  If oXMLDoc.Load(sFileName) Then
     MsgBox sFileName & " successfully loaded"
  Else
  ' Set ParseError Object
    Set xPE = oXMLDoc.parseError

    With xPE
      strErrText = "Load Error " & .ErrorCode & " XML File " & vbCrLf & _
        Replace(.URL, "file:///", "") & vbCrLf & vbCrLf & _
        xPE.reason & _
        "Source Text: " & .srcText & vbCrLf & vbCrLf & _
        "Line No:    " & .Line & vbCrLf & _
        "Line Pos:  " & .linepos & vbCrLf & _
        "File Pos:  " & .filepos & vbCrLf & vbCrLf
    End With
    MsgBox strErrText, vbExclamation
    Set xPE = Nothing
    Set oXMLDoc = Nothing
   'Stop procedure
    Exit Sub
  End If
' =================================
' 3 Set only one Nodelist
' =================================
  Set oXMLRowNodeList = oXMLDoc.DocumentElement.SelectNodes("rng/*/*")

' =================================
' 4. loop through all (row) nodes
' =================================
  For Each oXMLNode In oXMLRowNodeList
     Debug.Print oXMLNode.Text
   ' read in ...
  Next oXMLNode

 ' 5. terminate oXMLDoc
  Set oXMLDoc = Nothing
 End Sub

备注此代码通过通配符只将一个NodeList设置为col标记来避免过多的循环(因为col和row节点没有兄弟姐妹)。此外,如果这实际上代表您的根节点,我会引用DocumentElement而不是使用// saveStates。