Ms access Access VBA-如何下载XML文件并将其数据输入记录集

Ms access Access VBA-如何下载XML文件并将其数据输入记录集,ms-access,vba,ms-access-2007,Ms Access,Vba,Ms Access 2007,我将一个XML从网站转换成字符串strXML。 然后创建一个XML DOM文档: Dim xmlDoc As MSXML2.DOMDocument Dim xmlElement As MSXML2.IXMLDOMElement Dim xmlNode As MSXML2.IXMLDOMElement Set xmlDoc = New MSXML2.DOMDocument xmlDoc.loadXML (strXML) DisplayNode x

我将一个XML从网站转换成字符串strXML。 然后创建一个XML DOM文档:

    Dim xmlDoc As MSXML2.DOMDocument
    Dim xmlElement As MSXML2.IXMLDOMElement
    Dim xmlNode As MSXML2.IXMLDOMElement

    Set xmlDoc = New MSXML2.DOMDocument

    xmlDoc.loadXML (strXML)
    DisplayNode xmlDoc.childNodes
现在,DisplayNode是一种递归方法,它对XML数据中的每一行都调用自己:

Public Sub DisplayNode(ByRef Nodes As MSXML2.IXMLDOMNodeList)
Dim xNode As MSXML2.IXMLDOMNode

For Each xNode In Nodes
  If xNode.nodeType = NODE_TEXT Then
    Debug.Print xNode.parentNode.nodeName & " = " & xNode.nodeValue
  Else
    If xNode.parentNode.nodeName = "data" Then Debug.Print "*** NEW RECORD ***"
  End If

  If xNode.hasChildNodes Then
     DisplayNode xNode.childNodes
     Debug.Print "> recursive call - next field<"
  End If

Next xNode

End Sub
Public子显示节点(ByRef节点作为MSXML2.IXMLDOMNodeList)
将xNode设置为MSXML2.IXMLDOMNode
对于节点中的每个xNode
如果xNode.nodeType=NODE\u TEXT,则
Debug.Print xNode.parentNode.nodeName&“=”&xNode.nodeValue
其他的
如果xNode.parentNode.nodeName=“data”,则调试。打印“***新记录***”
如果结束
如果xNode.hasChildNodes,则
DisplayNode xNode.childNodes

Debug.Print“>递归调用-下一个字段您可以使用
MSXML2.IXMLDOMNode.selectNode()
通过xpath表达式显式选择节点?这样,您可以跟踪哪些字段/记录是从外部输入的。

这是一个可行的解决方案。下面的方法需要位于Access表单中,该表单将显示XML数据。表单中的文本字段应设置为其“控制源”与字段具有相同的名称在ADODB记录集中添加

Private Sub GetXMLdata()
 On Error GoTo ErrorHandler

'************************************************************
'CREATE AN ADODB RECORDSET - this recordset is in memory only it does not create a table in the database file
'This requires a reference addedd in TOOLS > References, Microsfot ActiveX Data Object , the latest version...
'************************************************************

 Dim rs As ADODB.Recordset
 Dim fld As ADODB.field
 Dim strXML As String


    Set rs = New ADODB.Recordset
    With rs
        .Fields.Append "EventID", adVarChar, 15, adFldMayBeNull
        .Fields.Append "JobDescription", adVarChar, 255, adFldMayBeNull
        .Fields.Append "FullName", adVarChar, 100, adFldMayBeNull
        .Fields.Append "CustomerID", adVarChar, 15, adFldMayBeNull
        .Fields.Append "CustomerAddress", adVarChar, 255, adFldMayBeNull
        .Fields.Append "Town", adVarChar, 64, adFldMayBeNull
        .Fields.Append "PostCode", adVarChar, 20, adFldMayBeNull
        .CursorType = adOpenKeyset
        .CursorLocation = adUseClient
        .LockType = adLockPessimistic
        .Open
    End With

'**********************************************************
'DOWNLOAD XML DATA 
'**********************************************************


    Dim obj As MSXML2.ServerXMLHTTP
    Set obj = New MSXML2.ServerXMLHTTP

    bj.Open "GET", "http://www.myserver.com/mydata.xml", False
    'in case you are sending a form *POST* or XML data to a SOAP server set content type
    obj.setRequestHeader "Content-Type", "text/xml"    
    obj.send

    Dim status As Integer
    status = obj.status

    If status >= 400 And status <= 599 Then
        Debug.Print "Error Occurred : " & obj.status & " - " & obj.statusText
    End If


   '********************************************************** 
   'CREATE XML DOM DOCUMENT  
   '**********************************************************   

    Dim xmlDoc As MSXML2.DOMDocument
    Dim xmlElement As MSXML2.IXMLDOMElement
    Dim xmlNode As MSXML2.IXMLDOMElement

    Set xmlDoc = New MSXML2.DOMDocument

    xmlDoc.loadXML (obj.responseText)


'**********************************************************
'LOAD XML DATA INTO THE RECORDSET 
'********************************************************** 

    LoadNodesIntoRs xmlDoc.childNodes, rs, 0

    If rs.recordCount > 0 Then

        rs.Update

    'BOUND THIS RECORDSET TO THE FORM
        Set Me.Recordset = rs

        End If

    Exit Sub


ErrorHandler:

    MsgBox Err.Description

End Sub
Private子GetXMLdata()
关于错误转到错误处理程序
'************************************************************
'创建ADODB记录集-此记录集仅在内存中,而不在数据库文件中创建表
'这需要在工具>引用、MicrosoftActiveX数据对象、最新版本中添加引用。。。
'************************************************************
将rs设置为ADODB.Recordset
将fld设置为ADODB.field
将strXML设置为字符串
Set rs=New ADODB.Recordset
用rs
.Fields.Append“EventID”,adVarChar,15,adFldMayBeNull
.Fields.Append“JobDescription”,adVarChar,255,adFldMayBeNull
.Fields.Append“全名”,adVarChar,100,adFldMayBeNull
.Fields.Append“CustomerID”,adVarChar,15,adFldMayBeNull
.Fields.Append“CustomerAddress”,adVarChar,255,adFldMayBeNull
.Fields.Append“Town”,adVarChar,64岁,adFldMayBeNull
.Fields.Append“PostCode”,adVarChar,20,adFldMayBeNull
.CursorType=adOpenKeyset
.CursorLocation=adUseClient
.LockType=adlock悲观
打开
以
'**********************************************************
'下载XML数据
'**********************************************************
Dim obj作为MSXML2.ServerXMLHTTP
Set obj=New MSXML2.ServerXMLHTTP
bj.打开“获取”http://www.myserver.com/mydata.xml”“错
'如果您正在向SOAP服务器集内容类型发送表单*POST*或XML数据
obj.setRequestHeader“内容类型”、“文本/xml”
发送对象
Dim状态为整数
状态=对象状态
如果状态>=400且状态为0,则
rs.更新
'将此记录集绑定到窗体
设置我。记录集=rs
如果结束
出口接头
错误处理程序:
MsgBox错误说明
端接头
下面的方法将逐个字段输入传递的记录集中。因为MSXML2似乎跳过空标记,如
,每个带有数据的标记名都需要按名称进行检查,并输入到相应的记录集字段中

Public Sub LoadNodesIntoRs(ByRef nodes As MSXML2.IXMLDOMNodeList, rs As ADODB.Recordset, recordCount As Integer)
    Dim xNode As MSXML2.IXMLDOMNode
    Dim fieldIndex As Integer

    For Each xNode In nodes
        If xNode.nodeType = NODE_TEXT Then
            'a field - actual data
        'note that MSXML2 will skip any node which contain no data like <COMPANY></COMPANY>

            Select Case xNode.parentNode.nodeName
                Case "EVENTID"
                    fieldIndex = 0
                Case "DESCRIPTION"
                    fieldIndex = 1
                Case "NAME"
                    fieldIndex = 2
                Case "CUSTOMERID"
                    fieldIndex = 3
                Case "ADDRESS"
                    fieldIndex = 4
                Case "TOWN"
                    fieldIndex = 5
                Case "POSTALCODE"
                    fieldIndex = 6
            End Select

            rs(fieldIndex) = xNode.nodeValue


        Else

            'CHECK FOR THE NODE WHICH CONTAINS THE SETS OF DATA'
            If xNode.parentNode.nodeName = "data" Then
                'next record
                If recordCount > 0 Then
                    'save previous record
                    rs.Update
                    fieldIndex = 0
                End If
                rs.AddNew
                recordCount = recordCount + 1
            End If


        End If

        If xNode.hasChildNodes Then
           'recurive call for the next node 
          LoadNodesIntoRs xNode.childNodes, rs, recordCount
        End If

    Next xNode

End Sub
Public Sub-LoadNodesIntoRs(ByRef节点作为MSXML2.IXMLDOMNodeList,rs作为ADODB.Recordset,recordCount作为整数)
将xNode设置为MSXML2.IXMLDOMNode
Dim字段索引为整数
对于节点中的每个xNode
如果xNode.nodeType=NODE\u TEXT,则
'字段-实际数据
'请注意,MSXML2将跳过任何不包含数据的节点,如
选择案例xNode.parentNode.nodeName
案例“EVENTID”
fieldIndex=0
案例“说明”
fieldIndex=1
案例“名称”
fieldIndex=2
案例“CUSTOMERID”
fieldIndex=3
案例“地址”
字段索引=4
案例“城镇”
字段索引=5
“后代码”案例
字段索引=6
结束选择
rs(fieldIndex)=xNode.nodeValue
其他的
'检查包含数据集的节点'
如果xNode.parentNode.nodeName=“数据”,则
“下一个记录
如果recordCount>0,则
'保存以前的记录
rs.更新
fieldIndex=0
如果结束
艾德纽卢比
recordCount=recordCount+1
如果结束
如果结束
如果xNode.hasChildNodes,则
'重新驱动下一个节点的调用
LoadNodesIntoRs xNode.childNodes、rs、recordCount
如果结束
下一个xNode
端接头

如果您想将此数据放入(表格)记录集中,则假定它也是“表格”的(即,不是深度嵌套的)?如果是这种情况,那么跳过递归并使用两个嵌套循环来处理它会容易得多。格式是预先确定的,还是您正在尝试处理任何XML?那么您不需要递归,将数据放入记录集中会更容易…您能发布XML的示例吗?谢谢Tim,但没有必要,我已经找到了一个以一种足够简单的方式使用递归模式的方法。我稍后将发布我的解决方案。VBA字符串变量绝对不限于255个字符。你从哪里得到这个疯狂的想法的?疯狂的是,我删除了它。
Public Sub LoadNodesIntoRs(ByRef nodes As MSXML2.IXMLDOMNodeList, rs As ADODB.Recordset, recordCount As Integer)
    Dim xNode As MSXML2.IXMLDOMNode
    Dim fieldIndex As Integer

    For Each xNode In nodes
        If xNode.nodeType = NODE_TEXT Then
            'a field - actual data
        'note that MSXML2 will skip any node which contain no data like <COMPANY></COMPANY>

            Select Case xNode.parentNode.nodeName
                Case "EVENTID"
                    fieldIndex = 0
                Case "DESCRIPTION"
                    fieldIndex = 1
                Case "NAME"
                    fieldIndex = 2
                Case "CUSTOMERID"
                    fieldIndex = 3
                Case "ADDRESS"
                    fieldIndex = 4
                Case "TOWN"
                    fieldIndex = 5
                Case "POSTALCODE"
                    fieldIndex = 6
            End Select

            rs(fieldIndex) = xNode.nodeValue


        Else

            'CHECK FOR THE NODE WHICH CONTAINS THE SETS OF DATA'
            If xNode.parentNode.nodeName = "data" Then
                'next record
                If recordCount > 0 Then
                    'save previous record
                    rs.Update
                    fieldIndex = 0
                End If
                rs.AddNew
                recordCount = recordCount + 1
            End If


        End If

        If xNode.hasChildNodes Then
           'recurive call for the next node 
          LoadNodesIntoRs xNode.childNodes, rs, recordCount
        End If

    Next xNode

End Sub