简体   繁体   中英

Flatten an XML with xslt then Import into Access

I've been trying for 3 weeks to use an XML file in Access. I've tried a couple of tactics such as converting to CSV and having a linked table but favour flattening the XML then importing it with VBA. I've seen lots of helpful examples and have learned a lot, but none of them let me complete the job. I'm a bit of a novice. It's important I understand as I need to take on a bigger XML file next, so I'll be adapting the XSLT to suit the bigger file next, inspired by your help.

A snippet of the XML is here:

<?xml version="1.0" encoding="UTF-8"?>
<STOREITEMS><PRODUCT ITEM="R7876" NAME="Gloves Pair">
        <STOCK>No Stock.</STOCK></PRODUCT>
    <PRODUCT ITEM="BR122293" NAME="Silver Duo Balls">
        <STOCK>In Stock</STOCK></PRODUCT>
    <PRODUCT ITEM="cloneboyb" NAME="Cast Your Own Kit">
        <STOCK>In Stock</STOCK></PRODUCT>
    <PRODUCT ITEM="ASTRO" NAME="Astroglide">
        <STOCK>In Stock</STOCK></PRODUCT>
    <PRODUCT ITEM="3002028110" NAME="Translucence Pink">
    <STOCK>In Stock</STOCK></PRODUCT>
    <PRODUCT ITEM="0340" NAME="Cream 82g Lubricant">
        <STOCK>No Stock.</STOCK></PRODUCT>
</STOREITEMS>

To be compatible with Access I need:

<?xml version="1.0" encoding="UTF-8"?>
<STOCK>
    <PRODUCT>
        <ITEM>R7876</ITEM>
        <NAME>Gloves Pair</NAME>
        <STOCK>No Stock.</STOCK>
    </PRODUCT>
    <PRODUCT>
        <ITEM>BR122293</ITEM>
        <NAME>Silver Duo Balls</NAME>
        <STOCK>In Stock</STOCK>
    </PRODUCT>
    <PRODUCT>
        <ITEM>cloneboyb</ITEM>
        <NAME>Cast Your Own Kit</NAME>
        <STOCK>In Stock</STOCK>
    </PRODUCT>
    <PRODUCT>
        <ITEM>ASTRO</ITEM>
        <NAME>Astroglide</NAME>
        <STOCK>In Stock</STOCK>
    </PRODUCT>
    <PRODUCT>
        <ITEM>3002028110</ITEM>
        <NAME>Translucence Pink</NAME>
        <STOCK>In Stock</STOCK>
    </PRODUCT>
    <PRODUCT>
        <ITEM>0340</ITEM>
        <NAME>Cream 82g Lubricant</NAME>
        <STOCK>No Stock.</STOCK>
    </PRODUCT>
</STOCK>

Most of what I've tried is an adaption of things I've seen elsewhere on here so I don't particularly have a starting point.

The VBA script I'm using to apply the transform and import the new XML file is the following:

Dim domIn As DOMDocument30
    Dim domOut As DOMDocument30
    Dim domStylesheet As DOMDocument30
    Dim xFile As String
    Dim StyleSheet As String
    Dim NewStock As String

    StyleSheet = "path to XSL"
    xFile = "path to xml"
    NewStock = "path to intended csv"
    Set domIn = New DOMDocument30

    domIn.async = False

    'Open the ADO xml document
    If domIn.Load(xFile) Then

        'Load the stylesheet
        Set domStylesheet = New DOMDocument30
        domStylesheet.Load StyleSheet

    'Apply the transform
    If Not domStylesheet Is Nothing Then
        Set domOut = New DOMDocument30
        domIn.transformNodeToObject domStylesheet, domOut

        'Save the output
        domOut.Save NewStock

        'Import the saved document into Access
        'Application.ImportXML NewStock
    End If
End If

'Cleanup
Set domIn = Nothing
Set domOut = Nothing
Set domStylesheet = Nothing

MsgBox "done!", , "ImportXMLFromADO"

I look forward to seeing pointers and thank you in advance.

The XSLT needed seems to be rather basic, just write a template to transform the attributes of PRODUCT elements into child elements and handle the rest with the identity transformation template:

<xsl:stylesheet
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    version="1.0">

  <xsl:strip-space elements="*"/>
  <xsl:output indent="yes"/>

  <xsl:template match="@* | node()">
    <xsl:copy>
      <xsl:apply-templates select="@* | node()"/>
    </xsl:copy>
  </xsl:template>

  <xsl:template match="PRODUCT/@*">
      <xsl:element name="{name()}">
          <xsl:value-of select="."/>
      </xsl:element>
  </xsl:template>

</xsl:stylesheet>

https://xsltfiddle.liberty-development.net/94hvTAm/1

As mentioned, consider XSLT to convert XML to CSV. Then, if needed data should be saved as a table, have MS Access import resulting CSV file with DoCmd.TransferText .

XSLT

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    version="1.0">
  <xsl:output method="text"/>
  <xsl:variable name="quote">&quot;</xsl:variable>

  <xsl:template match="/STOREITEMS">
      <xsl:text>"ITEM","NAME","STOCK"</xsl:text><xsl:text>&#xa;</xsl:text>
      <xsl:apply-templates select="PRODUCT"/>
  </xsl:template>

  <xsl:template match="PRODUCT">
    <xsl:value-of select="concat($quote, @ITEM, $quote, ',',
                                 $quote, @NAME, $quote, ',', 
                                 $quote, STOCK, $quote)"/>
    <xsl:if test="position()!=last()"><xsl:text>&#xa;</xsl:text></xsl:if>
  </xsl:template>

</xsl:stylesheet>

XSLT Demo

VBA (no domOut, only text written to file)

Dim domIn As New DOMDocument30, domStylesheet As New DOMDocument30
Dim xFile As String, StyleSheet As String, NewStock As String, xmlText As String
Dim fso As Object, oFile As Object

StyleSheet = "path to XSL"
xFile = "path to xml"
NewStock = "path to intended csv"

'LOAD INPUT XML
domIn.async = False
If domIn.Load(xFile) Then
    'LOAD STYLESHEET
    domStylesheet.Load StyleSheet

    'APPLY TRANSFORMATION, SAVE TO TEXT
    If Not domStylesheet Is Nothing Then
       xmlText = domIn.transformNode(domStylesheet)

       ' SAVE CSV
       Set fso = CreateObject("Scripting.FileSystemObject")
       Set oFile = fso.CreateTextFile(NewStock)
           oFile.WriteLine xmlText
       oFile.Close

       'IMPORT CSV INTO MS ACCESS
       DoCmd.TransferText acImportDelim, , "myTableName", NewStock, True, , 65001
    End If
End If

'CLEAN UP
Set domIn = Nothing: Set domStylesheet = Nothing
Set oFile = Nothing: Set fso = Nothing

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM