3

我有一个类似于以下结构的 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 中粘贴 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

4

1 回答 1

5

你的循环全错了。不要使用计数循环。有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 个短函数的作用比一个长函数的作用更明显。
于 2012-07-16T15:05:23.643 回答