使用xslt展平XML,然后导入Access

时间:2018-12-07 14:53:37

标签: xml vba csv ms-access xslt

我已经尝试了3个星期在Access中使用XML文件。我尝试了几种策略,例如转换为CSV并具有链接表,但倾向于将XML扁平化,然后通过VBA导入。 我看过很多有用的例子,也学到了很多东西,但是没有一个让我完成工作。我有点新手。 理解这一点很重要,因为我接下来需要处理一个更大的XML文件,因此在您的帮助下,我将对XSLT进行适应以适应下一个更大的文件。

XML的代码段在这里:

<?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>

要与Access兼容,我需要:

<?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>

我尝试过的大多数内容都是我在这里其他地方看到的东西的改编,所以我没有一个特别的起点。

我用于应用转换和导入新XML文件的VBA脚本如下:

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"

我期待见到指针,并在此先感谢您。

2 个答案:

答案 0 :(得分:0)

所需的XSLT似乎很基本,只需编写一个模板即可将PRODUCT元素的属性转换为子元素,然后使用身份转换模板处理其余部分:

<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

答案 1 :(得分:0)

如上所述,考虑使用XSLT将XML转换为CSV。然后,如果需要的数据应另存为表,请MS Access使用DoCmd.TransferText导入生成的CSV文件。

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 (无domOut,仅文本写入文件)

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