2013-04-25 50 views
2

我有一個XML文檔,看起來像這樣:提取多個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> 

有一個很多更多的山坳節點,每一個包含幾千行元素。

我想從行元素解析出價值,並最終將它們放到一個電子表格。我目前正在這樣做,如下所示:

' 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 

I.e.我循環遍歷col節點,然後遍歷每個行節點以獲取值A,B,C,D等。當行元素的數量達到數以萬計時,它的速度非常緩慢。

我沒有從XML文檔解析了豐富的經驗,我正在尋找一種方式來提取從所有的值「行*」在同一時間節點,無需通過他們不必循環。這可能嗎?

回答

0

也許你可以使用ADO DB記錄在記錄打開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 
+0

謝謝 - 這是一個好主意,但不能用於加載我使用的是隨機尋找XML。它必須已經通過記錄集保存爲xml。我會回來,但在一分鐘我不想與XML佈局 – chrisSpaceman 2013-04-29 15:24:05

+0

混亂也許你可以試試這個:在Excel XML(http://www.jkp-ads.com/Articles/XMLAndExcel05 .asp的) – 2013-04-29 15:42:38

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 

備註此代碼由通過外卡只有一個節點列表設置爲您山坳標籤避免過多的循環(如山坳和行節點沒有兄弟姐妹)。此外,我會參考DocumentElement而不是使用// saveStates,如果這實際上代表您的根節點。