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

Posted

技术标签:

【中文标题】使用 xslt 展平 XML,然后导入 Access【英文标题】:Flatten an XML with xslt then Import into Access 【发布时间】:2019-05-09 08:38:48 【问题描述】:

我已经尝试了 3 周来在 Access 中使用 XML 文件。我尝试了一些策略,例如转换为 CSV 并拥有一个链接表,但我更喜欢扁平化 XML,然后使用 VBA 将其导入。 我看过很多有用的例子,也学到了很多,但没有一个能让我完成这项工作。我有点新手。 我理解这一点很重要,因为接下来我需要处理一个更大的 XML 文件,因此在您的帮助下,我将调整 XSLT 以适应更大的文件。

XML 的 sn-p 在这里:

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

期待各位指点指点,提前谢谢大家。

【问题讨论】:

为什么需要 MS Access? XSLT 可以直接将 XML 转换为 CSV。在此网站上搜索此类示例。 不是这个 xml 文件。我确实首先尝试了最简单的选项,并在这个网站上花了很多时间查看示例。 Access 无法导入属性,因此对于有问题的 xml 文件,您从直接导入中得到的只是库存字段,无法知道它与哪个项目相关联。 MS 访问是我们用于 crm 和库存管理的工具。它与我们的供应商、市场和网站同步。它还连接到我们在仓库中的承运人。 明白。因此,您需要将 XML 数据保存在数据库中,而不仅仅是转换为 CSV。 【参考方案1】:

所需的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

【讨论】:

非常感谢,这也很完美,我从中吸取了教训。我也会在需要导入的其他一些文件上使用这种策略。【参考方案2】:

如前所述,考虑使用 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

【讨论】:

爱它,我确实尝试过这种方法,但无法成功。这很完美。非常感谢。 很高兴听到。不要忘记 *** 的说法 thanks。

以上是关于使用 xslt 展平 XML,然后导入 Access的主要内容,如果未能解决你的问题,请参考以下文章

XML XSLT 使用 SAXON EE10.6 流式传输大型 xml 文件

数字标签 <images> XSLT / XML

如何使用 XSLT 显示 XSD 验证的 XML

XSLT 无效令牌导致 XML 文档无效

自动生成XSLT - 通用/默认XSLT

使用 xslt 创建语言选择器