2

我有一个看起来像这样的 xml 文档:

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

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 文档方面没有太多经验,我正在寻找一种方法来同时从“行*”节点中提取所有值,而不必遍历它们。这可能吗?

4

2 回答 2

0

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

这是来自 MSDN 的一些示例代码:How to get 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
于 2013-04-25T11:22:49.647 回答
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。

于 2017-07-21T18:21:16.923 回答