Solved

Import XML with attributes in childnodes (Ms Access)

Posted on 2008-10-11
10
2,366 Views
Last Modified: 2013-11-27
Dear Experts,

I'm trying to import an XML file like shown below into an ms access database.
All values should be stored in the same table (SGH_XML_RESPONSE)
Table :
XML_Response_Key (Int, Key, Autonum)
Ordernr (Txt)
Correct_Verwerkt (Txt)
ResultaatCode (Txt)
Omschrijving (Txt)
Response_Text (Memo, (Complete XML file stored as string))
AddDate (Date/Time)
Addwho (Txt)

XML File Example:

  <?xml version="1.0" ?>
- <Resultaat>
- <AfmeldResultaat OrderNr="SOR0513073" CorrectVerwerkt="false" ResultaatCode="KlantOngeldig">
  <Omschrijving>Gegevens op de melding SOR0513073 konden niet gevonden worden.</Omschrijving>
  </AfmeldResultaat>
- <AfmeldResultaat OrderNr="SOR0513145" CorrectVerwerkt="false" ResultaatCode="GlastypeOngeldig">
  <Omschrijving>Glastype iso494 kan niet gevonden worden.</Omschrijving>
  </AfmeldResultaat>
  </Resultaat>

The problem are the attributes in AfmeldResultaat (Attribute Ordernr,  CorrectVerwerkt and ResultaatCode).
Is there somebody who knows how to handle these attributed?

Code so far :

Function Call : fImportXML stXMLResponseString, "SGH_XML_RESPONSE"

Function fImportXML(strXML As String, strTableName As String)
   
    Dim xmlDOM  As DOMDocument
    Dim xmlNodeList As IXMLDOMNodeList
    Dim xmlNodeItem As IXMLDOMNode
    Dim xmlNodeField As IXMLDOMNode
    Dim rst As DAO.Recordset

    Set xmlDOM = New DOMDocument
    xmlDOM.LoadXML strXML

    Set xmlNodeList = xmlDOM.getElementsByTagName("OrderNr")
    Set rst = CurrentDb.OpenRecordset(strTableName)

    With rst
        For Each xmlNodeItem In xmlNodeList
            .AddNew
            For Each xmlNodeField In xmlNodeItem.ChildNodes
                .Fields(xmlNodeField.nodeName).Value = xmlNodeField.Text
            Next
            .Update
        Next
        .Close
    End With
End Function

Any help would be highly appriciated!

Thanks in advance
0
Comment
Question by:jrameuwissen
  • 6
  • 4
10 Comments
 
LVL 2

Expert Comment

by:DrCabbage
ID: 22695641
Could you just add after the  existing ForEach another one to loop through the attributes as follows:

    For Each xmlNodeAttribute In xmlNodeItem.attributes
                .Fields(xmlNodeAttribute.Name).Value = xmlNodeAttribute.Value
    Next


0
 
LVL 1

Author Comment

by:jrameuwissen
ID: 22696755
Thanks for your reply DrCabbage.
I changed the function but the table is still not populated (also no errors though) :

Function fImportXML(strXML As String, strTableName As String)
   
    Dim xmlDOM  As DOMDocument
    Dim xmlNodeList As IXMLDOMNodeList
    Dim xmlNodeItem As IXMLDOMNode
    Dim xmlNodeField As IXMLDOMNode
    Dim xmlNodeAttribute As IXMLDOMAttribute
    Dim rst As DAO.Recordset

    Set xmlDOM = New DOMDocument
    xmlDOM.LoadXML strXML

    Set xmlNodeList = xmlDOM.getElementsByTagName("Afmeldresultaat")
    Set rst = CurrentDb.OpenRecordset(strTableName)

    With rst
        For Each xmlNodeItem In xmlNodeList
            .AddNew
            For Each xmlNodeField In xmlNodeItem.ChildNodes
                For Each xmlNodeAttribute In xmlNodeItem.Attributes
                    .Fields(xmlNodeAttribute.Name).Value = xmlNodeAttribute.Value
                Next
                .Fields(xmlNodeField.nodeName).Value = xmlNodeField.Text
            Next
            .Update
        Next
        .Close
    End With

End Function

Is there something I'm missing?

Thanks.
0
 
LVL 2

Expert Comment

by:DrCabbage
ID: 22699149
Sorry, I should have been clearer exactly where to put the second "For Each".

Because the attributes are on the outer node, that's what the foreach should be on - if you nest it as you have done, you're looping through the attributes on each child node (but the child nodes have no attributes). What I meant was to have a second foreach - after looping through the child nodes of AfmeldResultaat, we loop through the attributes of AfmeldResultaat:

With rst
        For Each xmlNodeItem In xmlNodeList
            .AddNew
            For Each xmlNodeField In xmlNodeItem.ChildNodes
                .Fields(xmlNodeField.nodeName).Value = xmlNodeField.Text
            Next
            For Each xmlNodeAttribute In xmlNodeItem.Attributes
                    .Fields(xmlNodeAttribute.Name).Value = xmlNodeAttribute.Value
             Next
            .Update
        Next
        .Close
    End With
0
 
LVL 1

Author Comment

by:jrameuwissen
ID: 22700777
DrCabbage,

I must be missing something. I'm still not able to populate the table.
Still no errormessage occures...
Any ideas? Thanks in advance!

Function fImportXML(strXML As String, strTableName As String)
   
    Dim xmlDOM  As DOMDocument
    Dim xmlNodeList As IXMLDOMNodeList
    Dim xmlNodeItem As IXMLDOMNode
    Dim xmlNodeField As IXMLDOMNode
    Dim xmlNodeAttribute As IXMLDOMAttribute
    Dim rst As DAO.Recordset

    Set xmlDOM = New DOMDocument
    xmlDOM.LoadXML strXML
   
    Set xmlNodeList = xmlDOM.getElementsByTagName("AfmeldResultaat")
    Set rst = CurrentDb.OpenRecordset(strTableName)

    With rst
       For Each xmlNodeItem In xmlNodeList
           .AddNew
           For Each xmlNodeField In xmlNodeItem.ChildNodes
               .Fields(xmlNodeField.nodeName).Value = xmlNodeField.Text
           Next
           For Each xmlNodeAttribute In xmlNodeItem.Attributes
                   .Fields(xmlNodeAttribute.Name).Value = xmlNodeAttribute.Value
            Next
           .Update
       Next
       .Close
   End With


End Function
0
 
LVL 1

Author Comment

by:jrameuwissen
ID: 22701004
Could it be the getElementsByTagName tag (Afmeldresultaat) is incorrect?
Or maybe the string I pass to the function? The string consists out of the innertext element of the webbrowser....
0
Comprehensive Backup Solutions for Microsoft

Acronis protects the complete Microsoft technology stack: Windows Server, Windows PC, laptop and Surface data; Microsoft business applications; Microsoft Hyper-V; Azure VMs; Microsoft Windows Server 2016; Microsoft Exchange 2016 and SQL Server 2016.

 
LVL 2

Expert Comment

by:DrCabbage
ID: 22705109
It might be useful to set a breakpoint after the line

Set xmlNodeList = xmlDOM.getElementsByTagName("AfmeldResultaat")

and just check with the debugger that xmlNodeList has some entries (you can navigate through the DOM this way, which I've found very helpful for spotting bugs.

It might also be an idea to add a little error-checking code in case there is something wrong with the XML, for example :

 xmlDOM.LoadXML strXML
If (xmlDOM.parseError.errorCode <> 0) Then
     Dim myErr
     Set myErr = xmlDOM.parseError
     MsgBox("An XML Parse error occurred: " & myErr.reason)
End If

0
 
LVL 1

Author Comment

by:jrameuwissen
ID: 22705468
Thanks DrCabbage,

I added your code :

If (xmlDOM.parseError.errorCode <> 0) Then
    Dim myErr
    Set myErr = xmlDOM.parseError
    MsgBox("An XML Parse error occurred: " & myErr.reason)
End If

I receive errormessage : Invalid XML Declaration...
Any ideas?
0
 
LVL 2

Accepted Solution

by:
DrCabbage earned 500 total points
ID: 22707431
Is your XML just like the example? You would need to remove the extra "-" signs, but otherwise it looks OK to me.

You can find out more of the parseError members at
http://msdn.microsoft.com/en-us/library/ms767720(VS.85).aspx

which would allow you to give the line where the error occurred - but the other thing I'm wondering is what encoding your file is in and whether you need an encoding declaration (or whether it works if you ditch the <?xml line altogether?
0
 
LVL 1

Author Comment

by:jrameuwissen
ID: 22709334
DrCabbage, you nailed it!!! I changed the code (see below) and it works just fine now!
Removing the <?xml line made it work.

Dim replaceLine As String
stXMLResponseString = Innertext
stXMLResponseString = Replace(stXMLResponseString, "-", "")
replaceLine = "<?xml version=" & Chr(34) & "1.0" & Chr(34) & " ?>"
stXMLResponseString = Replace(stXMLResponseString, replaceLine, "")
fImportXML stXMLResponseString2, "SGH_XML_Response"

Function fImportXML(strXML As String, strTableName As String)
   
Dim xmlDOM  As DOMDocument
Dim xmlNodeList As IXMLDOMNodeList
Dim xmlNodeItem As IXMLDOMNode
Dim xmlNodeField As IXMLDOMNode
Dim xmlNodeAttribute As IXMLDOMAttribute
Dim rst As DAO.Recordset
Dim errordesc As String

    Set xmlDOM = New DOMDocument
    xmlDOM.LoadXML strXML
   
    If (xmlDOM.parseError.ErrorCode <> 0) Then
        Dim myErr
        Set myErr = xmlDOM.parseError
        MsgBox ("An XML Parse error occurred: " & myErr.reason)
        errordesc = "Application encountered an Error while trying to import XML response from Meldkamer in Function [fImportXML]" & vbNewLine & myErr
        Call ErrorLogging(errordesc, "IMPORT RESPONSE", Err.Number, Err.Description)
        Exit Function
    End If
   
    Set xmlNodeList = xmlDOM.getElementsByTagName("AfmeldResultaat")
    Set rst = CurrentDb.OpenRecordset(strTableName)

    With rst
       For Each xmlNodeItem In xmlNodeList
           .AddNew
           For Each xmlNodeField In xmlNodeItem.ChildNodes
               .Fields(xmlNodeField.nodeName).Value = xmlNodeField.Text
           Next
           For Each xmlNodeAttribute In xmlNodeItem.Attributes
                   .Fields(xmlNodeAttribute.Name).Value = xmlNodeAttribute.Value
            Next
            rst.Fields("Response_Text") = strXML
           .Update
       Next
       .Close
   End With

End Function

Thanks a lot for your help!
Points rewarded of course.
0
 
LVL 1

Author Comment

by:jrameuwissen
ID: 22709350
Oeps, the function call should be
fImportXML stXMLResponseString, "SGH_XML_Response"

Regards, Johan

0

Featured Post

Is Your Active Directory as Secure as You Think?

More than 75% of all records are compromised because of the loss or theft of a privileged credential. Experts have been exploring Active Directory infrastructure to identify key threats and establish best practices for keeping data safe. Attend this month’s webinar to learn more.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

When you are entering numbers in a speadsheet, and don't remember what 6×7 is, you just type “=6*7" instead. It works in every cell! This is not so in Access. To enter the elusive 42 in a text box, you have to find a calculator, and then copy the re…
I originally created this report in Crystal Reports 2008 where there is an option to underlay sections. I initially came across the problem in Access Reports where I was unable to run my border lines down through the entire page as I was using the P…
Familiarize people with the process of utilizing SQL Server functions from within Microsoft Access. Microsoft Access is a very powerful client/server development tool. One of the SQL Server objects that you can interact with from within Microsoft Ac…
In Microsoft Access, learn how to use Dlookup and other domain aggregate functions and one method of specifying a string value within a string. Specify the first argument, which is the expression to be returned: Specify the second argument, which …

861 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

25 Experts available now in Live!

Get 1:1 Help Now