Не удается получить содержимое определенного узла из XML-файла в vba - PullRequest
1 голос
/ 07 ноября 2019

Я пытаюсь получить определенный узел из XML-файла через VBA. Есть условие на месте. Если узел "Boolean.text" = "false", тогда мне нужно иметь содержимое узла "Комментарий", однако, с кодом, который я использую, я постоянно получаю сообщение об ошибке "Ошибка выполнения 91, переменная объекта или переменная блока не установлена«on line» If (goodBad.hasChildNodes) Тогда «Я не могу понять, что я делаю неправильно. У меня также есть ощущение, что я использую способ сложного кода для этого довольно простого запроса.

Надеюсь, кто-нибудь может дать мне руководство.

Sub ReadXMLFile2()
    Dim xDoc As New MSXML2.DOMDocument60
    Dim strXMLFilePath As String
    Dim list As IXMLDOMNodeList
    Dim resp As IXMLDOMNode
    Dim goodFalse As IXMLDOMNode
    Dim goodBad As IXMLDOMNode
    Dim reason As IXMLDOMNode
    Dim textNodes As IXMLDOMNode
    Dim node As IXMLDOMNode
    Dim attr As IXMLDOMAttribute
    Dim childNode As IXMLDOMNode
    Dim strReason As String

    Set xDoc = New MSXML2.DOMDocument60
    strXMLFilePath = CurrentProject.Path & "\Test.xml"

    With xDoc
        .async = False
        .validateOnParse = True

        If Not xDoc.Load(strXMLFilePath) Then
            Debug.Print .parseError.reason, .parseError.ErrorCode
        End If
    End With

    Set list = xDoc.selectNodes("//ToBeCheckedResp/CheckResp/Resp")

    For Each resp In list
        Set attr = resp.Attributes.getNamedItem("status")

        If (Not attr Is Nothing) Then
            Debug.Print attr.Text
        End If

        If resp.hasChildNodes Then
            For Each childNode In resp.childNodes
                Set goodFalse = childNode.selectSingleNode("Boolean")
                Debug.Print goodFalse.Text
            Next childNode
        End If

        If goodFalse.Text = "true" Then
            strReason = ""
        ElseIf goodFalse.Text = "false" Then
            If resp.hasChildNodes Then
                Set goodBad = resp.selectSingleNode("False")
                If (goodBad.hasChildNodes) Then
                    Set reason = goodBad.selectSingleNode("Why")
                    If reason.hasChildNodes Then
                        Set textNodes = reason.selectNodes("Comment")
                        For Each node In textNodes
                            strReason = strReason & " " & node.Text
                        Next node
                    End If
                End If
            End If
        End If

    Next resp
    Set xDoc = Nothing

End Sub

Используемый файл XML:

<?xml version="1.0" encoding="UTF-8"?>
<ToBeCheckedResp>
 <CheckResp>
  <Resp status="completed">
   <Value>
    <Boolean>true</Boolean>
    <Good>
     <Example>Test1</Example>
    </Good>
   </Value>
  </Resp>
  <Resp status="completed">
   <Value>
    <Boolean>false</Boolean>
    <False>
     <Why>
      <Comment>Reason why boolean is false.</Comment>
     </Why>
    </False>
   </Value>
  </Resp>
 </CheckResp>
</ToBeCheckedResp>

1 Ответ

1 голос
/ 07 ноября 2019
        Set goodBad = resp.selectSingleNode("False")
        If (goodBad.hasChildNodes) Then

Ошибка 91 здесь означает, что goodBad равно Nothing, что означает, что selectSingleNode не дал узла с именем False в resp.

Похожевам нужен узел Value;предположительно selectSingleNode не будет проходить через дочерние узлы / потомки, чтобы найти имя узла, которое вы дали, и этот узел <Value> будет в пути.

Итак, выберите узел <Value>, а затемselectSingleNode из этого узла. Или используйте другой метод, который выполняет обход потомков, чтобы найти конкретный узел.

В любом случае методы, которые могут возвращать Nothing, не должны всегда возвращать действительную ссылку на объект.

Если выполнение может быть разумно возобновлено без нужного вам узла, тогда вы должны принять меры против Nothing, чтобы предотвратить совершение недопустимого вызова члена для неверной ссылки на объект:

    Set goodBad = resp.selectSingleNode("False")
    If Not goodBad Is Nothing Then
        If (goodBad.hasChildNodes) Then
            '...
        End If
    Else
        'goodBad node doesn't exist. What now?
        '...
    End If

В противном случае выможно сделать предположение явным с помощью Debug.Assert:

    Set goodBad = resp.selectSingleNode("False")
    Debug.Assert Not goodBad Is Nothing
    If (goodBad.hasChildNodes) Then

Если утверждение не подтверждено, тогда выполнение сразу останавливается, и вы можете отлаживать и возобновлять.

Что касается сложности,это связано с жестким кодированием иерархии узлов (resp является родителем goodBad и т. д.) и обходом узлов по отдельности. Возможно, вы могли бы упростить все это с помощью более точно настроенных selectNodes запросов XPath.

...