Muhammad Adeel Ahmed
Muhammad Adeel Ahmed

Reputation: 43

MSXML2.DOMDocument60 - Reading XML in VBA with Namespace

I am new in programming in Access and with MSXML2.DOMDocument60 so please accept my apologies if anything is not correct. I am trying to parse an xml but I am facing issue when loading it using MSXML2.DOMDocument. The structrue of the XML is shown below:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE raml SYSTEM 'raml20.dtd'>
<raml version="2.0" xmlns="raml20.xsd">
  <cmData type="actual">
    <header>
      <log dateTime="2021-03-11T13:00:47.000Z" action="created" appInfo="ActualExporter">InternalValues are used</log>
    </header>
    <managedObject class="RETU_R" version="EQMR20A_2003_002" distName="PLMN-PLMN/MRBTS-503327/EQM_R-1/APEQM_R-1/ALD_R-1/RETU_R-1" id="136127888">
      <p name="angle">20</p>
      <list name="antBandList">
        <item>
          <p name="antBeamwidth">61</p>
          <p name="antFreqBand">1</p>
          <p name="antOperGain">185</p>
        </item>
        <item>
          <p name="antBeamwidth">60</p>
          <p name="antFreqBand">2</p>
          <p name="antOperGain">185</p>
        </item>
        <item>
          <p name="antBeamwidth">61</p>
          <p name="antFreqBand">3</p>
          <p name="antOperGain">184</p>
        </item>
      </list>
      <p name="antBearing">2800</p>
      <p name="antModel">80010825-2.1_L</p>
      <p name="antSerial">DEG3535443</p>
      <list name="antlDNList">
        <p>external</p>
      </list>
      <p name="baseStationID">45118</p>
      <p name="configDN">MRBTS-503327/EQM-1/APEQM-1/ALD-9/RETU-1</p>
      <p name="installDate">240814</p>
      <p name="installerID">CRCTL</p>
      <p name="maxAngle">60</p>
      <p name="mechanicalAngle">0</p>
      <p name="minAngle">0</p>
      <p name="operationalState">1</p>
      <p name="sectorID">3U21</p>
      <p name="subunitNumber">1</p>
    </managedObject>
    
  </cmData>
</raml>

I understand my code has Namespace which is possibly causing all the issues. I created the error decode Message in my vba and I get the following error :

"Could not load the document: C:\Audit_DB\Input Files\Test1.xml
Error when loading was: The element 'raml' is used but not declared in the DTD/Schema."

Can someone advise how can i skip the namespace here and if there is anything wrong with the vba code. The code I have created is below:

Sub XMLRead()

Dim path As String
Dim firstNameField As MSXML2.IXMLDOMNodeList
Dim lists As MSXML2.IXMLDOMNodeList
Dim raml As MSXML2.IXMLDOMElement

Dim i As Integer
Dim objXML As MSXML2.DOMDocument60
Set objXML = New MSXML2.DOMDocument60
path = "C:\Audit_DB\Input Files\Test1.xml"

objXML.SetProperty "ProhibitDTD", False

With objXML
    .async = False
    .Load path
    .SetProperty "SelectionLanguage", "XPath"
    .SetProperty "ProhibitDTD", False
    .SetProperty "SelectionNamespaces", "xmlns:raml='raml20.xsd'"
    Set nodeList = .selectNodes("//managedObject")
End With


If objXML.Load(path) Then
    Debug.Print "Success"
Else
    Debug.Print "Could not load the document: " & path
    If objXML.parseError.errorCode <> 0 Then Debug.Print "Error when loading was: " + objXML.parseError.reason
End If
    
Set xobjdetails = objXML.childNodes(0)
Set xObject = objXML.firstChild
    

Debug.Print objXML.selectNodes("//managedObject").length

End Sub

Upvotes: 2

Views: 7963

Answers (2)

Tomalak
Tomalak

Reputation: 338426

The XML parser is trying to honor the document type declaration:

<!DOCTYPE raml SYSTEM 'raml20.dtd'>

You can either provide the raml20.dtd file so that the XML parser can find it when it loads the XML, or you can disable the automatic validation and the resolution of external references (such as DTDs) in your DOMDocument (see MSDN):

With objXML
    ' ...
    .resolveExternals = False
    .validateOnParse = False
    ' ...
    .load "filepath"
End With

Both settings must be disabled, or the load will not succeed. Make sure you set them before trying to load the file.


That being said, //managedObject won't find anything because that node is in the raml20.xsd namespace, just like all of the other elements in your document.

You've already bound that namespace to the prefix raml (with .SetProperty "SelectionNamespaces", "xmlns:raml='raml20.xsd'"), but you need to use the prefix, too:

Debug.Print objXML.selectNodes("//raml:managedObject").length

Finally, your VBA code needs some clean-up. You set ProhibitDTD twice, and you call .load more than once, too.

Upvotes: 5

artnib
artnib

Reputation: 508

With objXML
    ...
    .validateOnParse = False
    ...
End With

Upvotes: 2

Related Questions