I have a Microsoft Access database (via Office 2010) which is being used to manage course data, and I need to regularly export this data to a particular XML structure.
U
I can't quite re-create your issue in MS Access. I went through the manual XML Export wizard and Saved Export and both produce the same result, namely your last format where first two related tables (Courses and Occurrences) are nested with last table (OccurrenceUnits) stacked at the end. What I can say is your saved export is contingent on established relationships between tables and not simply an export of table or inner join SQL query of tables.
However, consider a programming solution that specifically automates your exact structural needs. And what you need involves XSLT (the declarative programming language that re-styles, re-formats, re-structures XML documents). VBA can transform XML with XSLT scripts using the MSXML object. You can continue to run your saved export (using table relationships) and then load the external XML and XSLT files for the transformation.
XSLT (save as external .xsl or .xslt to be used below)
<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"
xmlns:od="urn:schemas-microsoft-com:officedata"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
exclude-result-prefixes="od xsi">
<xsl:output version="1.0" encoding="UTF-8" indent="yes" />
<xsl:strip-space elements="*"/>
<!-- Identity Transform -->
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="Courses">
<Courses>
<xsl:copy-of select="CourseID"/>
<xsl:copy-of select="CourseTitle"/>
<xsl:for-each select="Occurences">
<xsl:copy-of select="*"/>
<xsl:variable name="occid" select="OccurenceID"/>
<xsl:copy-of select="../../OccurrencesUnits[OccurenceID=$occid]"/>
</xsl:for-each>
</Courses>
</xsl:template>
<xsl:template match="OccurrencesUnits"/>
</xsl:transform>
VBA subroutine (use behind command button or trigger event)
Below are two options of XML export: 1) using your Saved Export object or 2) the automated Application.ExportXML where you add other related tables to Courses output:
Private Sub XMLOutput_Click()
Dim rawDoc As Object, xslDoc As Object, newDoc As Object
Dim xmlstr As String, xslstr As String
Dim otherTables As AdditionalData
Set otherTables = Application.CreateAdditionalData
otherTables.Add "Occurrences"
otherTables.Add "OccurrencesUnits"
otherTables.Add "Units"
' RUN SAVED XML EXPORT '
'DoCmd.RunSavedImportExport "SavedXMLExportName"
' RUN AUTOMATED EXPORT XML WITH NESTED ADDITIONAL TABLES '
Application.ExportXML acExportTable, "Courses", "C:\Path\To\Original\XMLfile.xml", _
, , , , , , AdditionalData:=otherTables
' LOAD XML AND XSL FILES '
xmlstr = "C:\Path\To\Original\XMLfile.xml"
xslstr = "C:\Path\To\XSLT\Script.xsl"
Set rawDoc = CreateObject("MSXML2.DOMDocument")
Set xslDoc = CreateObject("MSXML2.DOMDocument")
Set newDoc = CreateObject("MSXML2.DOMDocument")
rawDoc.async = False
rawDoc.Load xmlstr
xslDoc.async = False
xslDoc.Load xslstr
' TRANSFORM TO NEW XML '
rawDoc.transformNodeToObject xslDoc, newDoc
' SAVE NEW XML FILE '
newDoc.Save "C:\Path\To\Output\XMLfile.xml"
MsgBox "Successfully transformed xml!", vbInformation
End Sub