如何在不使用任何 ETL 工具的情况下将 XML 解析为平面文件或任何关系数据库

How to parse XML into flatfile or any relational db without using any ETL tool

我有一些任务要将 XML 中的记录生成到 CSV 或任何数据库中。我知道如果我可以使用 ETL 工具会更容易,但我的客户想使用一些方法来解析 CSV 中的那些 XML 或任何关系数据库,如 sql 服务器,而不会有任何复杂性。如果可以使用一些 API 或一些 javascript/tsql 或者可能是我可能不知道的其他方法。

我需要分享一些可以在这里使用的想法,既可以在单一方法中使用,也可以在两种方法中使用,比如先 XML 到 CSV,然后 CSV 到 sql。对于第二种方法,我可以使用 sqloader,但对于第一种方法,我需要一些帮助。我在这里分享我的 XML,以及我期待的输出。如果有人可以与我分享,请分享您的想法或任何代码片段。

为了进一步输入这些 XML 我每个月都会像邮递员一样从 API 输出中获取。因此,如果可以一起使用,那也很好。我有多个 XML 需要一起解析,这里我分享一个示例 XML.

和一个示例区域,例如 https://dbfiddle.uk/?rdbms=sqlserver_2014,我可以在其中测试您的代码。您可以保存文件并File1.xml

欢迎各种建议。提前致谢。

输入XML

<feed xmlns="pppp//www.xxx.org/2005/Atom" xmlns:m="pppp//xxxx/ado/2007/08/dataservices/metadata" xmlns:d="pppp//xxxx/ado/2007/08/dataservices" xml:base="pppp//BW.SAP.SETS.EU:443/sap/opu/odata/sap/SSC_24_KPI/">
        <id>pppp//pppp//xxxx/id</id>
        <title type="text">SSC_24_KPI_V1Results</title>
        <updated>2019-11-08T13:37:56Z</updated>
        <author>
            <name/>
        </author>
        <link href="SSC_24_KPI_V1Results" rel="self" title="SSC_24_KPI_V1Results"/>
        <entry>
            <id>pppp//pppp//xxxx/id('V2.77.5')</id>
            <title type="text">SSC_24_KPI_V1Results('V2.77.5')</title>
            <updated>2019-11-08T13:37:56Z</updated>
            <category term="SSC_24_KPI.SSC_24_KPI_V1Results" scheme="pppp//xxxx/scheme"/>
            <link href="SSC_24_KPI_V1Results('V2.77.5')" rel="self" title="SSC_24_KPI_V1Results"/>
            <content type="application/xml">
                <m:prop xmlns:m="pppp//xxxx/ado/2007/08/dataservices/metadata" xmlns:d="pppp//xxxx/ado/2007/08/dataservices">
                    <d:ACCNT_GRP_ID>Z001</d:ACCNT_GRP_ID>
                    <d:ACCT_GRP>EU Bank</d:ACCT_GRP>
                    <d:VAY_FLAG>N</d:VAY_FLAG>
                    <d:CUST_COUNT>15600</d:CUST_COUNT>
                </m:prop>
            </content>
        </entry>
        <entry>
            <id>pppp//pppp//xxxx/id('V2.77.6')</id>
            <title type="text">SSC_24_KPI_V1Results('V2.77.6')</title>
            <updated>2019-11-08T13:37:56Z</updated>
            <category term="SSC_24_KPI.SSC_24_KPI_V1Results" scheme="pppp//xxxx/scheme"/>
            <link href="SSC_24_KPI_V1Results('V2.77.6')" rel="self" title="SSC_24_KPI_V1Results"/>
            <content type="application/xml">
                <m:prop xmlns:m="pppp//xxxx/ado/2007/08/dataservices/metadata" xmlns:d="pppp//xxxx/ado/2007/08/dataservices">
                    <d:ACCNT_GRP_ID>Z001</d:ACCNT_GRP_ID>
                    <d:ACCT_GRP>EU Bank</d:ACCT_GRP>
                    <d:VAY_FLAG>Y</d:VAY_FLAG>
                    <d:CUST_COUNT>900</d:CUST_COUNT>
                </m:prop>
            </content>
        </entry>
        <entry>
            <id>pppp//pppp//xxxx/id('V2.77.7')</id>
            <title type="text">SSC_24_KPI_V1Results('V2.77.7')</title>
            <updated>2019-11-08T13:37:56Z</updated>
            <category term="SSC_24_KPI.SSC_24_KPI_V1Results" scheme="pppp//xxxx/scheme"/>
            <link href="SSC_24_KPI_V1Results('V2.77.7')" rel="self" title="SSC_24_KPI_V1Results"/>
            <content type="application/xml">
                <m:prop xmlns:m="pppp//xxxx/ado/2007/08/dataservices/metadata" xmlns:d="pppp//xxxx/ado/2007/08/dataservices">
                    <d:ACCNT_GRP_ID>Z002</d:ACCNT_GRP_ID>
                    <d:ACCT_GRP>Card Companies NO</d:ACCT_GRP>
                    <d:VAY_FLAG>N</d:VAY_FLAG>
                    <d:CUST_COUNT>100</d:CUST_COUNT>
                </m:prop>
            </content>
        </entry>
        <entry>
            <id>pppp//pppp//xxxx/id('V2.77.8')</id>
            <title type="text">SSC_24_KPI_V1Results('V2.77.8')</title>
            <updated>2019-11-08T13:37:56Z</updated>
            <category term="SSC_24_KPI.SSC_24_KPI_V1Results" scheme="pppp//xxxx/scheme"/>
            <link href="SSC_24_KPI_V1Results('V2.77.8')" rel="self" title="SSC_24_KPI_V1Results"/>
            <content type="application/xml">
                <m:prop xmlns:m="pppp//xxxx/ado/2007/08/dataservices/metadata" xmlns:d="pppp//xxxx/ado/2007/08/dataservices">
                    <d:ACCNT_GRP_ID>Z002</d:ACCNT_GRP_ID>
                    <d:ACCT_GRP>Card Companies NO</d:ACCT_GRP>
                    <d:VAY_FLAG>Y</d:VAY_FLAG>
                    <d:CUST_COUNT>3000</d:CUST_COUNT>
                </m:prop>
            </content>
        </entry>
    </feed>

输出

您可以像这里一样尝试:

假设:您知道如何将此 XML 读入变量...

DECLARE @xml XML=
N'<feed xmlns="pppp//www.xxx.org/2005/Atom" xmlns:m="pppp//xxxx/ado/2007/08/dataservices/metadata" xmlns:d="pppp//xxxx/ado/2007/08/dataservices" xml:base="pppp//BW.SAP.SETS.EU:443/sap/opu/odata/sap/SSC_24_KPI/">
  <id>pppp//pppp//xxxx/id</id>
  <title type="text">SSC_24_KPI_V1Results</title>
  <updated>2019-11-08T13:37:56Z</updated>
  <author>
    <name />
  </author>
  <link href="SSC_24_KPI_V1Results" rel="self" title="SSC_24_KPI_V1Results" />
  <entry>
    <id>pppp//pppp//xxxx/id(''V2.77.5'')</id>
    <title type="text">SSC_24_KPI_V1Results(''V2.77.5'')</title>
    <updated>2019-11-08T13:37:56Z</updated>
    <category term="SSC_24_KPI.SSC_24_KPI_V1Results" scheme="pppp//xxxx/scheme" />
    <link href="SSC_24_KPI_V1Results(''V2.77.5'')" rel="self" title="SSC_24_KPI_V1Results" />
    <content type="application/xml">
      <m:prop xmlns:m="pppp//xxxx/ado/2007/08/dataservices/metadata" xmlns:d="pppp//xxxx/ado/2007/08/dataservices">
        <d:ACCNT_GRP_ID>Z001</d:ACCNT_GRP_ID>
        <d:ACCT_GRP>EU Bank</d:ACCT_GRP>
        <d:VAY_FLAG>N</d:VAY_FLAG>
        <d:CUST_COUNT>15600</d:CUST_COUNT>
      </m:prop>
    </content>
  </entry>
  <entry>
    <id>pppp//pppp//xxxx/id(''V2.77.6'')</id>
    <title type="text">SSC_24_KPI_V1Results(''V2.77.6'')</title>
    <updated>2019-11-08T13:37:56Z</updated>
    <category term="SSC_24_KPI.SSC_24_KPI_V1Results" scheme="pppp//xxxx/scheme" />
    <link href="SSC_24_KPI_V1Results(''V2.77.6'')" rel="self" title="SSC_24_KPI_V1Results" />
    <content type="application/xml">
      <m:prop xmlns:m="pppp//xxxx/ado/2007/08/dataservices/metadata" xmlns:d="pppp//xxxx/ado/2007/08/dataservices">
        <d:ACCNT_GRP_ID>Z001</d:ACCNT_GRP_ID>
        <d:ACCT_GRP>EU Bank</d:ACCT_GRP>
        <d:VAY_FLAG>Y</d:VAY_FLAG>
        <d:CUST_COUNT>900</d:CUST_COUNT>
      </m:prop>
    </content>
  </entry>
  <entry>
    <id>pppp//pppp//xxxx/id(''V2.77.7'')</id>
    <title type="text">SSC_24_KPI_V1Results(''V2.77.7'')</title>
    <updated>2019-11-08T13:37:56Z</updated>
    <category term="SSC_24_KPI.SSC_24_KPI_V1Results" scheme="pppp//xxxx/scheme" />
    <link href="SSC_24_KPI_V1Results(''V2.77.7'')" rel="self" title="SSC_24_KPI_V1Results" />
    <content type="application/xml">
      <m:prop xmlns:m="pppp//xxxx/ado/2007/08/dataservices/metadata" xmlns:d="pppp//xxxx/ado/2007/08/dataservices">
        <d:ACCNT_GRP_ID>Z002</d:ACCNT_GRP_ID>
        <d:ACCT_GRP>Card Companies NO</d:ACCT_GRP>
        <d:VAY_FLAG>N</d:VAY_FLAG>
        <d:CUST_COUNT>100</d:CUST_COUNT>
      </m:prop>
    </content>
  </entry>
  <entry>
    <id>pppp//pppp//xxxx/id(''V2.77.8'')</id>
    <title type="text">SSC_24_KPI_V1Results(''V2.77.8'')</title>
    <updated>2019-11-08T13:37:56Z</updated>
    <category term="SSC_24_KPI.SSC_24_KPI_V1Results" scheme="pppp//xxxx/scheme" />
    <link href="SSC_24_KPI_V1Results(''V2.77.8'')" rel="self" title="SSC_24_KPI_V1Results" />
    <content type="application/xml">
      <m:prop xmlns:m="pppp//xxxx/ado/2007/08/dataservices/metadata" xmlns:d="pppp//xxxx/ado/2007/08/dataservices">
        <d:ACCNT_GRP_ID>Z002</d:ACCNT_GRP_ID>
        <d:ACCT_GRP>Card Companies NO</d:ACCT_GRP>
        <d:VAY_FLAG>Y</d:VAY_FLAG>
        <d:CUST_COUNT>3000</d:CUST_COUNT>
      </m:prop>
    </content>
  </entry>
</feed>';

--查询

WITH XMLNAMESPACES(DEFAULT 'pppp//www.xxx.org/2005/Atom' 
                  ,'pppp//xxxx/ado/2007/08/dataservices/metadata' AS m
                  ,'pppp//xxxx/ado/2007/08/dataservices' AS d
                  ,'pppp//BW.SAP.SETS.EU:443/sap/opu/odata/sap/SSC_24_KPI/' AS base)
select @xml.value('(/feed/updated/text())[1]','datetime') AS UPDATED
      ,entr.value('(content/m:prop/d:ACCNT_GRP_ID/text())[1]','nvarchar(100)') AS ACCNT_GRP_ID
      ,entr.value('(content/m:prop/d:ACCT_GRP/text())[1]','nvarchar(100)') AS ACCT_GRP
      ,entr.value('(content/m:prop/d:VAY_FLAG/text())[1]','nvarchar(10)') AS VAY_FLAG
      ,entr.value('(content/m:prop/d:CUST_COUNT/text())[1]','nvarchar(10)') AS CUST_COUNT
FROM @xml.nodes('/feed/entry') A(entr);

结果

+-------------------------+--------------+-------------------+----------+------------+
| UPDATED                 | ACCNT_GRP_ID | ACCT_GRP          | VAY_FLAG | CUST_COUNT |
+-------------------------+--------------+-------------------+----------+------------+
| 2019-11-08 13:37:56.000 | Z001         | EU Bank           | N        | 15600      |
+-------------------------+--------------+-------------------+----------+------------+
| 2019-11-08 13:37:56.000 | Z001         | EU Bank           | Y        | 900        |
+-------------------------+--------------+-------------------+----------+------------+
| 2019-11-08 13:37:56.000 | Z002         | Card Companies NO | N        | 100        |
+-------------------------+--------------+-------------------+----------+------------+
| 2019-11-08 13:37:56.000 | Z002         | Card Companies NO | Y        | 3000       |
+-------------------------+--------------+-------------------+----------+------------+

简而言之:

  • 有各种命名空间,需要在开头声明。
  • 重复元素(<entry> 元素)使用 .nodes() 检索。
  • 从这些重复的 entr 行中,我们可以使用相对 XPath 进行读取。
  • Header 数据(所有在你的 XML 中只存在一次的东西)直接使用 .value().
  • 读取