Jon Jaques
asked on
Generic XML Import for Access
Hello Experts,
I'm working on some XML data transfers between a website and an access database; the website, built in PHP, has pages which return an XML file (a web service, basically) for a given table of data. The XML is always "generic", like this:
<?xml version="1.0" encoding="iso-8859-1"?>
<export>
<row>
<somefield1>dadas</somefie ld1>
<somefield2>werwerwer</som efield2>
<somefield3>sdfsdfsdfsdfsd fsdf/somef ield3>
</row>
<row>
<somefield1>dadas</somefie ld1>
<somefield2>werwerwer</som efield2>
<somefield3>sdfsdfsdfsdfsd fsdf/somef ield3>
</row>
</export>
I use the msxml object to get the response, and now I want to create a generic function which will enumerate that xml, inserting or updating records as it goes.
The function should be called like this:
ImportXML(xmlhttp.response Text, "tblUsers", "UserID")
Private Function ImportXML(strXML as String, strTableName as String, strPKey as String)
'' Loop through each <row> element of strXML
'' Check for existence of strPKey
'' Update record if exists
'' Add New record if not
End Function
I've found lots of great examples already here on EE, but my head's starting to spin, and I'd really apprecaite some help building out this function!
Any ideas are greatly appreciated!
--Jon
PS, I'm not using Application.ImportXML because it has a bad habit of crashing access and giving no reason for it!
I'm working on some XML data transfers between a website and an access database; the website, built in PHP, has pages which return an XML file (a web service, basically) for a given table of data. The XML is always "generic", like this:
<?xml version="1.0" encoding="iso-8859-1"?>
<export>
<row>
<somefield1>dadas</somefie
<somefield2>werwerwer</som
<somefield3>sdfsdfsdfsdfsd
</row>
<row>
<somefield1>dadas</somefie
<somefield2>werwerwer</som
<somefield3>sdfsdfsdfsdfsd
</row>
</export>
I use the msxml object to get the response, and now I want to create a generic function which will enumerate that xml, inserting or updating records as it goes.
The function should be called like this:
ImportXML(xmlhttp.response
Private Function ImportXML(strXML as String, strTableName as String, strPKey as String)
'' Loop through each <row> element of strXML
'' Check for existence of strPKey
'' Update record if exists
'' Add New record if not
End Function
I've found lots of great examples already here on EE, but my head's starting to spin, and I'd really apprecaite some help building out this function!
Any ideas are greatly appreciated!
--Jon
PS, I'm not using Application.ImportXML because it has a bad habit of crashing access and giving no reason for it!
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
Hello,
Yes, the fields will be named exactly the same in the XML as in the table, and all tables use an autonumber of the primary key...
Technically, the first field of each <row> will be the primary key field, but I thought it would make it easier to check for the pre-existence of a record if you could say something like this:
Dim RecordID as variant, strXMLValue as String
strXMLValue = xmlnode.value
RecordID = dlookup(strPKey, strTableName, strPKey & " = " & strXMLValue)
if RecordID > 0 then
'' Record already exists, update
else
'' Record does not exist, add new
end if
Thanks for the help!!!
Yes, the fields will be named exactly the same in the XML as in the table, and all tables use an autonumber of the primary key...
Technically, the first field of each <row> will be the primary key field, but I thought it would make it easier to check for the pre-existence of a record if you could say something like this:
Dim RecordID as variant, strXMLValue as String
strXMLValue = xmlnode.value
RecordID = dlookup(strPKey, strTableName, strPKey & " = " & strXMLValue)
if RecordID > 0 then
'' Record already exists, update
else
'' Record does not exist, add new
end if
Thanks for the help!!!
Ahh I see - so this isn't necessarily purely appending data - the possibility exists of it being edited records too?
ASKER
Yeah, man, I KNEW that code was supposed to be simple! Nice Job!
Your first layer there broke the XML down just the way I needed, although I must admit I have not tested it yet, but doing that now...
Your first layer there broke the XML down just the way I needed, although I must admit I have not tested it yet, but doing that now...
ASKER
Yes, editing; If data has changed on the site, I want to update the local records with that data.
OK - now we're added a bit more complexity. (Thankfully ;-)
Function fImportXML(strXML As String, strTableName As String, strPKey As String)
Dim xmlDOM As DOMDocument
Dim xmlNodeList As IXMLDOMNodeList
Dim xmlNodeItem As IXMLDOMNode
Dim xmlNodeField As IXMLDOMNode
Dim rst As DAO.Recordset
Dim strDelim As String
Dim blnPK As Boolean
Dim blnAppend As Boolean
Dim intIndex As Integer
Set xmlDOM = New DOMDocument
xmlDOM.loadXML strXML
Set xmlNodeList = xmlDOM.getElementsByTagNam e("row")
If Len(strPKey) > 0 Then
For intIndex = 0 To xmlNodeList.Item(1).ChildN odes.Lengt h - 1
If xmlNodeList.Item(1).ChildN odes(intIn dex).nodeN ame = strPKey Then
blnPK = True
Exit For
End If
Next
End If
With CurrentDb.OpenRecordset(st rTableName , dbOpenDynaset)
If blnPK Then
strDelim = IIf(.Fields(strPKey).Type = dbText, """", "")
End If
For Each xmlNodeItem In xmlNodeList
If blnPK Then
.FindFirst strPKey & "=" & strDelim & xmlNodeItem.ChildNodes(int Index).Tex t & strDelim
If .NoMatch Then
blnAppend = True
.AddNew
Else
blnAppend = False
.Edit
End If
Else
.AddNew
End If
For Each xmlNodeField In xmlNodeItem.ChildNodes
If blnPK Then
If strPKey <> xmlNodeField.nodeName Or blnAppend Then
.Fields(xmlNodeField.nodeN ame).value = xmlNodeField.Text
End If
End If
Next
.Update
Next
.Close
End With
End Function
Function fImportXML(strXML As String, strTableName As String, strPKey As String)
Dim xmlDOM As DOMDocument
Dim xmlNodeList As IXMLDOMNodeList
Dim xmlNodeItem As IXMLDOMNode
Dim xmlNodeField As IXMLDOMNode
Dim rst As DAO.Recordset
Dim strDelim As String
Dim blnPK As Boolean
Dim blnAppend As Boolean
Dim intIndex As Integer
Set xmlDOM = New DOMDocument
xmlDOM.loadXML strXML
Set xmlNodeList = xmlDOM.getElementsByTagNam
If Len(strPKey) > 0 Then
For intIndex = 0 To xmlNodeList.Item(1).ChildN
If xmlNodeList.Item(1).ChildN
blnPK = True
Exit For
End If
Next
End If
With CurrentDb.OpenRecordset(st
If blnPK Then
strDelim = IIf(.Fields(strPKey).Type = dbText, """", "")
End If
For Each xmlNodeItem In xmlNodeList
If blnPK Then
.FindFirst strPKey & "=" & strDelim & xmlNodeItem.ChildNodes(int
If .NoMatch Then
blnAppend = True
.AddNew
Else
blnAppend = False
.Edit
End If
Else
.AddNew
End If
For Each xmlNodeField In xmlNodeItem.ChildNodes
If blnPK Then
If strPKey <> xmlNodeField.nodeName Or blnAppend Then
.Fields(xmlNodeField.nodeN
End If
End If
Next
.Update
Next
.Close
End With
End Function
ASKER
ROCK ON!
YOU NAILED THIS!
Thank you so much!
YOU NAILED THIS!
Thank you so much!
You're welcome. :-)
ASKER
This code is too good to keep to myself, and so I'm going to share it with my friends over on another forum -- do you have a preferred reference bit for credits at the top???? I'll also reference this thread.
Thanks again!
Thanks again!
Well I may not pilfer code from the greats - but I'll take inspiration from their copyright comment lines :-)
(i.e. Thanks to Dev and co and the Access Web)
'This code was originally written by Leigh Purvis.
'www.DatabaseDevelopment.co.uk
'It is not to be altered, distributed, coloured in or used for chips
'except as part of an application type thingy.
'You are free to use it in any application which doesn't suck,
'provided the copyright notice is left vaguely recognizable
'Or if you can think of something better to have in your modules instead
'you could shamelessly pretend to your boss that you came up with it :-)
'
'Code Courtesy of
'Leigh Purvis MSc MBCS ABC DEFG
(i.e. Thanks to Dev and co and the Access Web)
'This code was originally written by Leigh Purvis.
'www.DatabaseDevelopment.co.uk
'It is not to be altered, distributed, coloured in or used for chips
'except as part of an application type thingy.
'You are free to use it in any application which doesn't suck,
'provided the copyright notice is left vaguely recognizable
'Or if you can think of something better to have in your modules instead
'you could shamelessly pretend to your boss that you came up with it :-)
'
'Code Courtesy of
'Leigh Purvis MSc MBCS ABC DEFG
ASKER
Hahahahaha, beautiful, I love it!
ASKER
I have another question regarding how to add authentication to this -- If I post another question, would you mind taking a look at it?
I'll try to - of course someone else might offer help in the new question too - and that's rarely a bad thing.
After all - many voices make a choir :-)
(I can't sing though).
After all - many voices make a choir :-)
(I can't sing though).
What about the strPKey parameter? What's the relevance of passing that? (Do your tables use a natural key - or a surrogate like an autonumber?)