解析用VBA XML文件(Parse XML File with VBA)

2019-06-26 07:24发布

我有一个类似的结构的XML文件:

<egh_eval>
<eval_set>
    <eval_id>FLOAT</eval_id>
    <eval_d>
        <height>INT</height>
        <weight>INT</weight>
    </eval_d>
    <eval_e>
        <height>INT</height>
        <weight>INT</weight>
    </eval_e>
    <eval_cred>
        <credit>FLOAT</credit>
    </eval_cred>
</eval_set>

我需要解析完整的文件,并把它放在一个表。 (注:eval_d和eval_e实际上有一百多属性各自)。 我尝试使用MSXML2但是我被卡住,当我尝试解析文件。 通过使用在回答如何在VBA填写Flash XML和VBA中解析XML我能到那里:

Dim fSuccess As Boolean
Dim oDoc As MSXML2.DOMDocument
Dim oRoot As MSXML2.IXMLDOMNode ' Level 0 egh_eval
Dim oChild As MSXML2.IXMLDOMNode ' Level 1 eval_set
Dim oChildren As MSXML2.IXMLDOMNode ' Level 2 eval_id, eval_d, eval_e, eval_cred


Dim domList As MSXML2.IXMLDOMNodeList

Set oDoc = New MSXML2.DOMDocument
oDoc.async = False
oDoc.validateOnParse = False

fSuccess = oDoc.Load(Application.CurrentProject.Path & "\file.xml")

Set oRoot = oDoc.documentElement
Set oChild = oRoot.childNodes(0)
Set oChildren = oChild.childNodes(0)

For i = 0 To oChild.childNodes.length - 1
    For y = 0 To oChildren.childNodes.length - 1
        MsgBox oChildren.nodeName & " : " & oChildren.nodeTypedValue
        oChildren.childNodes.nextNode
    Next
    oChild.childNodes.nextNode
Next

然而,不是给我正确的价值观,它给了我在eval_id 4倍的浮...

谢谢 !

编辑:我使用Microsoft Access 2002 SP3

Answer 1:

你的循环是完全错误的。 不要使用计数循环。 还有For Each将做的正是你所需要的,这是更具可读性,太。

Dim egh_eval As MSXML2.IXMLDOMNode
Dim eval_set As MSXML2.IXMLDOMNode
Dim eval_prop As MSXML2.IXMLDOMNode

Set egh_eval = oDoc.documentElement.childNodes(0)

For Each eval_set In egh_eval.childNodes
  If eval_set.nodeType = NODE_ELEMENT Then
    For Each eval_prop In eval_set.childNodes
      If eval_prop.nodeType = NODE_ELEMENT Then
        MsgBox eval_prop.nodeName & " : " & eval_prop.childNodes.length
      End If
    Next eval_prop
  End If
Next eval_set

当您使用childNodes ,你必须检查的nodeType属性。 评论,文本节点等等都将在子节点,而不仅仅是元素的节点列表。

这可能是考虑使用XPath来选择你的元素是个好主意。 与DOM方法这样做很容易出错和繁琐。 阅读上IXMLDOMNode::selectNodesIXMLDOMNode::selectSingleNode

For Each eval_set In oDoc.selectNodes("/egh_eval/eval_set")
  Set eval_id = eval_set.selectSingleNode("eval_id")

  ' always check for empty search result!
  If Not eval_id Is Nothing Then
    MsgBox eval_id.text
    ' ...
  End If
Next eval_set

此外,在一般的笔记。 这个:

fSuccess = oDoc.Load(Application.CurrentProject.Path & "\file.xml")

实际上既没有必要,一个糟糕的主意,因为你似乎从来没有检查的价值也fSuccess )。 更好:

Sub LoadAndProcessXml(path As String)
  Dim oDoc As MSXML2.DOMDocument

  If oDoc.Load(path) Then
    ProcessXmlFile oDoc
  Else
    ' error handling
  End If
End Sub

Sub ProcessXml(doc As MSXML2.DOMDocument) 
  ' Process the contents like shown above
End Sub

创建多个潜艇/功能有以下几个优点

  • 使错误处理要容易得多,因为每个函数只有一个目的。
  • 您将需要更少的变量,因为你可以在函数参数定义一些变量
  • 代码将变得更易于维护,因为它比一个长的功能确实比较明显的什么3短功能做。


文章来源: Parse XML File with VBA