使用SQL将XML文件解析为特定列

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了使用SQL将XML文件解析为特定列相关的知识,希望对你有一定的参考价值。

我有一个XML文件,如下所示:

<?xml version="1.0" encoding = "utf-8"?>
<CIM CIMVERSION="2.0" DTDVERSION="2.0">
<MESSAGE ID="1111" PROTOCOLVERSION="1.0">
<SIMPLEREQ>
<VALUE.NAMEDINSTANCE>
<INSTANCENAME CLASSNAME="DCIM_ControllerView">
<KEYBINDING NAME="InstanceID">
<KEYVALUE VALUETYPE="string">RAID.Integrated.1-1</KEYVALUE>
</KEYBINDING>
</INSTANCENAME>
    <INSTANCE CLASSNAME="DCIM_ControllerView">
       <PROPERTY NAME="LastUpdateTime" TYPE="string">
         <VALUE>20170223172914.000000+000</VALUE>
         <DisplayValue>2017-02-23T17:29:14</DisplayValue>
       </PROPERTY>
       <PROPERTY NAME="LastSystemInventoryTime" TYPE="string">
         <VALUE>20170223172914.000000+000</VALUE>
         <DisplayValue>2017-02-23T17:29:14</DisplayValue>
       </PROPERTY>
       <PROPERTY NAME="RealtimeCapability" TYPE="uint32">
         <VALUE>6</VALUE>
         <DisplayValue>Capable</DisplayValue>
       </PROPERTY>
       <PROPERTY NAME="SupportControllerBootMode" TYPE="uint8">
         <VALUE>1</VALUE>
         <DisplayValue>Supported</DisplayValue>
       </PROPERTY>
       <PROPERTY NAME="SupportEnhancedAutoForeignImport" TYPE="uint8">
         <VALUE>1</VALUE>
         <DisplayValue>Supported</DisplayValue>
       </PROPERTY>
       <PROPERTY NAME="MaxAvailablePCILinkSpeed" TYPE="string">
         <VALUE>Generation 3</VALUE>
         <DisplayValue>Generation 3</DisplayValue>
       </PROPERTY>
       <PROPERTY NAME="MaxPossiblePCILinkSpeed" TYPE="string">
         <VALUE>Generation 3</VALUE>
         <DisplayValue>Generation 3</DisplayValue>
       </PROPERTY>
       <PROPERTY NAME="PatrolReadState" TYPE="uint8">
         <VALUE>1</VALUE>
         <DisplayValue>Stopped</DisplayValue>
       </PROPERTY>
       <PROPERTY NAME="DriverVersion" TYPE="string">
          <DisplayValue>Not Applicable</DisplayValue>
       </PROPERTY>
       <PROPERTY NAME="CacheSizeInMB" TYPE="uint32">
         <VALUE>0</VALUE>
         <DisplayValue>0 MB</DisplayValue>
       </PROPERTY>
       <PROPERTY NAME="SupportRAID10UnevenSpans" TYPE="uint8">
         <VALUE>1</VALUE>
         <DisplayValue>Supported</DisplayValue>
       </PROPERTY>
       <PROPERTY NAME="T10PICapability" TYPE="uint8">
         <VALUE>1</VALUE>
         <DisplayValue>Supported</DisplayValue>
       </PROPERTY>
       <PROPERTY NAME="SlicedVDCapability" TYPE="uint8">
         <VALUE>1</VALUE>
         <DisplayValue>Sliced Virtual Disk creation supported</DisplayValue>
       </PROPERTY>
       <PROPERTY NAME="CachecadeCapability" TYPE="uint8">
         <VALUE>0</VALUE>
         <DisplayValue>Cachecade Virtual Disk not supported</DisplayValue>
       </PROPERTY>
       <PROPERTY NAME="KeyID" TYPE="string">
         <DisplayValue/>
       </PROPERTY>
       <PROPERTY NAME="EncryptionCapability" TYPE="uint8">
         <VALUE>1</VALUE>
         <DisplayValue>Local Key Management Capable</DisplayValue>
       </PROPERTY>
       <PROPERTY NAME="EncryptionMode" TYPE="uint8">
         <VALUE>0</VALUE>
         <DisplayValue>None</DisplayValue>
       </PROPERTY>
       <PROPERTY NAME="SecurityStatus" TYPE="uint32">
         <VALUE>1</VALUE>
         <DisplayValue>Encryption Capable</DisplayValue>
       </PROPERTY>
       <PROPERTY NAME="SASAddress" TYPE="string">
         <VALUE>1111</VALUE>
         <DisplayValue>1111</DisplayValue>
       </PROPERTY>
       <PROPERTY NAME="ProductName" TYPE="string">
         <VALUE>PERC Mini</VALUE>
         <DisplayValue>PERC Mini</DisplayValue>
       </PROPERTY>
       <PROPERTY NAME="DeviceCardSlotType" TYPE="string">
         <VALUE>Unknown</VALUE>
         <DisplayValue>Unknown</DisplayValue>
       </PROPERTY>
       <PROPERTY NAME="DeviceCardSlotLength" TYPE="uint8">
         <VALUE>2</VALUE>
         <DisplayValue>Unknown</DisplayValue>
       </PROPERTY>
       <PROPERTY NAME="DeviceCardDataBusWidth" TYPE="string">
         <VALUE>Unknown</VALUE>
         <DisplayValue>Unknown</DisplayValue>
       </PROPERTY>
       <PROPERTY NAME="DeviceCardManufacturer" TYPE="string">
         <VALUE>DELL</VALUE>
         <DisplayValue>DELL</DisplayValue>
       </PROPERTY>
       <PROPERTY NAME="PCISubDeviceID" TYPE="string">
         <VALUE>1111</VALUE>
         <DisplayValue>1F47</DisplayValue>
       </PROPERTY>
       <PROPERTY NAME="PCIDeviceID" TYPE="string">
         <VALUE>1</VALUE>
         <DisplayValue>1</DisplayValue>
       </PROPERTY>
       <PROPERTY NAME="PCISubVendorID" TYPE="string">
         <VALUE>1</VALUE>
         <DisplayValue>1</DisplayValue>
       </PROPERTY>
       <PROPERTY NAME="PCIVendorID" TYPE="string">
         <VALUE>1</VALUE>
         <DisplayValue>1</DisplayValue>
       </PROPERTY>
       <PROPERTY NAME="Function" TYPE="string">
         <VALUE>0</VALUE>
         <DisplayValue>0</DisplayValue>
       </PROPERTY>
       <PROPERTY NAME="Device" TYPE="string">
         <VALUE>0</VALUE>
         <DisplayValue>0</DisplayValue>
       </PROPERTY>
       <PROPERTY NAME="Bus" TYPE="string">
         <VALUE>2</VALUE>
         <DisplayValue>2</DisplayValue>
       </PROPERTY>
       <PROPERTY NAME="ControllerFirmwareVersion" TYPE="string">
         <VALUE>00.00.00.00</VALUE>
         <DisplayValue>00.00.00.00</DisplayValue>
       </PROPERTY>
       <PROPERTY NAME="PCISlot" TYPE="uint8">
         <VALUE>0</VALUE>
         <DisplayValue>0</DisplayValue>
       </PROPERTY>
       <PROPERTY NAME="RollupStatus" TYPE="uint32">
         <VALUE>1</VALUE>
         <DisplayValue>OK</DisplayValue>
       </PROPERTY>
       <PROPERTY NAME="PrimaryStatus" TYPE="uint32">
         <VALUE>1</VALUE>
         <DisplayValue>OK</DisplayValue>
       </PROPERTY>
       <PROPERTY NAME="DeviceDescription" TYPE="string">
         <VALUE>Integrated RAID Controller 1</VALUE>
         <DisplayValue>Integrated RAID Controller 1</DisplayValue>
       </PROPERTY>
       <PROPERTY NAME="FQDD" TYPE="string">
         <VALUE>RAID.Integrated.1-1</VALUE>
         <DisplayValue>RAID.Integrated.1-1</DisplayValue>
       </PROPERTY>
       <PROPERTY NAME="InstanceID" TYPE="string">
         <VALUE>RAID.Integrated.1-1</VALUE>
         <DisplayValue>RAID.Integrated.1-1</DisplayValue>
       </PROPERTY>
    </INSTANCE>
</VALUE.NAMEDINSTANCE>
</SIMPLEREQ>
</MESSAGE>
</CIM>

我能够将SQL引入并作为XML对象读取。目前,我使用SSIS将XML文本放在一个字符串中。

在SSIS中读取文件后,它将它带入我的数据库,进入如下的临时表:

Staging Table

现在可以将文件放入我的临时表中,我想使用触发器将它们解析为特定的列。请注意,XML字符串是UTF-8。此数据来自Dell硬件清单XML文件。 他们的文档在此图中概述了他们的XML模式:

Diagram

我需要将XML数据转换为模仿该图的列格式。所以标题是:

CIM | Messgae | Classname | InstanceID | PropertyName |价值| DisplayValue

这些列将在XML中包含它们各自的数据

另外,正如我所提到的,它是utf-8格式。要在SQL中将其作为XML对象读取,我使用以下代码:

declare @XML xml
set @XML = (SELECT Top 1 REPLACE([XML], 'utf-8', 'utf-16')FROM [StagingTable])

SELECT @XML

此外,我有多个INSTANCENAME实例,其中有更多集INSTANCE,PROPERTY,VALUE,DISPLAYVALUE等。

以下是根据Dell文档的XML架构:

<?xml version="1.0" encoding="UTF-8"?>
<xs:schema targetNamespace="http://schemas.dell.com/HWinventory/1/0/events"
elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:evt="http://schemas.dell.com/HWinventory/1/0/events">
 <xs:element name="CIM">
 <xs:complexType>
 <xs:sequence>
 <xs:element name="MESSAGE">
 <xs:complexType>
 <xs:sequence>
 <xs:element name="SIMPLEREQ">
 <xs:complexType>
 <xs:sequence>
 <xs:element maxOccurs="unbounded" name="VALUE.NAMEDINSTANCE">
 <xs:complexType>
 <xs:sequence>
 <xs:element name="INSTANCENAME">
 <xs:complexType>
 <xs:sequence>
 <xs:element name="KEYBINDING">
 <xs:complexType>
 <xs:sequence>
 <xs:element name="KEYVALUE">
 <xs:complexType>
 <xs:simpleContent>
 <xs:extension base="xs:string">
 <xs:attribute name="VALUETYPE" type="xs:string" use="required" />
 </xs:extension>
 </xs:simpleContent>
 </xs:complexType>
 </xs:element>
 </xs:sequence>
<xs:attribute name="NAME" type="xs:string" use="required" />
 </xs:complexType>
 </xs:element>
 </xs:sequence>
<xs:attribute name="CLASSNAME" type="xs:string" use="required" />
 </xs:complexType>
 </xs:element>
 <xs:element name="INSTANCE">
 <xs:complexType>
 <xs:sequence>
 <xs:element minOccurs="0" name="PROPERTY.ARRAY">
 <xs:complexType>
 <xs:sequence>
 <xs:element name="VALUE.ARRAY">
 <xs:complexType>
 <xs:sequence>
 <xs:element name="VALUE" type="xs:string" />
 <xs:element name="DisplayValue" type="xs:string" />
 </xs:sequence>
 </xs:complexType>
 </xs:element>
 </xs:sequence>
<xs:attribute name="NAME" type="xs:string" use="required" />
 <xs:attribute name="TYPE" type="xs:string" use="required" />
 </xs:complexType>
 </xs:element>
<xs:element maxOccurs="unbounded" name="PROPERTY">
 <xs:complexType>
 <xs:sequence>
 <xs:element minOccurs="0" name="VALUE" type="xs:string" />
 <xs:element name="DisplayValue" type="xs:string" />
 </xs:sequence>
<xs:attribute name="NAME" type="xs:string" use="required" />
 <xs:attribute name="TYPE" type="xs:string" use="required" />
 </xs:complexType>
 </xs:element>
 </xs:sequence>
<xs:attribute name="CLASSNAME" type="xs:string" use="required" />
 </xs:complexType>
 </xs:element>
 </xs:sequence>
 </xs:complexType>
 </xs:element>
 </xs:sequence>
 </xs:complexType>
 </xs:element>
 </xs:sequence>
 <xs:attribute name="ID" type="xs:int" use="required" />
 <xs:attribute name="PROTOCOLVERSION" type="xs:decimal" use="required" />
 </xs:complexType>
 </xs:element>
 </xs:sequence>
答案

以下查询将从您的XML中检索各种数据。它不完全是您所需要的,但它应该为您提供一个模板,用于您可能想要提取的任何值:

DECLARE @xml XML=
N'<CIM CIMVERSION="2.0" DTDVERSION="2.0">
  <MESSAGE ID="4711" PROTOCOLVERSION="1.0">
    <SIMPLEREQ>
      <VALUE.NAMEDINSTANCE xmlns:fo="http://www.w3.org/1999/XSL/Format">
        <INSTANCENAME CLASSNAME="DCIM_ControllerView">
          <KEYBINDING NAME="InstanceID">
            <KEYVALUE VALUETYPE="string">RAID.Slot.1-1</KEYVALUE>
          </KEYBINDING>
        </INSTANCENAME>
        <INSTANCE CLASSNAME="DCIM_ControllerView">
          <PROPERTY NAME="DriverVersion" TYPE="string">
            <DisplayValue />
          </PROPERTY>
          <PROPERTY NAME="KeyID" TYPE="string">
            <DisplayValue />
          </PROPERTY>
          <PROPERTY NAME="SASAddress" TYPE="string">
            <VALUE>5782BCB00C577600</VALUE>
            <DisplayValue>5782BCB00C577600</DisplayValue>
          </PROPERTY>
          <PROPERTY NAME="ProductName" TYPE="string">
            <VALUE>PERC H310 Adapter</VALUE>
            <DisplayValue>PERC H310 Adapter</DisplayValue>
          </PROPERTY>
          <PROPERTY NAME="DeviceCardSlotType" TYPE="string">
            <VALUE>PCI Express x8</VALUE>
            <DisplayValue>PCI Express x8</DisplayValue>
          </PROPERTY>
          <PROPERTY NAME="DeviceCardManufacturer" TYPE="string">
            <VALUE>DELL</VALUE>
            <DisplayValue>DELL</DisplayValue>
          </PROPERTY>
          <PROPERTY NAME="PCISubDeviceID" TYPE="string">
            <VALUE>1F4E</VALUE>
            <DisplayValue>1F4E</DisplayValue>
          </PROPERTY>
          <PROPERTY NAME="PCIDeviceID" TYPE="string">
            <VALUE>73</VALUE>
            <DisplayValue>73</DisplayValue>
          </PROPERTY>
          <PROPERTY NAME="PCISubVendorID" TYPE="string">
            <VALUE>1028</VALUE>
            <DisplayValue>1028</DisplayValue>
          </PROPERTY>
          <PROPERTY NAME="PCIVendorID" TYPE="string">
            <VALUE>1000</VALUE>
            <DisplayValue>1000</DisplayValue>
          </PROPERTY>
          <PROPERTY NAME="Function" TYPE="string">
            <VALUE>0</VALUE>
            <DisplayValue>0</DisplayValue>
          </PROPERTY>
          <PROPERTY NAME="Device" TYPE="string">
            <VALUE>0</VALUE>
            <DisplayValue>0</DisplayValue>
          </PROPERTY>
          <PROPERTY NAME="Bus" TYPE="string">
            <VALUE>1</VALUE>
            <DisplayValue>1</DisplayValue>
          </PROPERTY>
          <PROPERTY NAME="ControllerFirmwareVersion" TYPE="string">
            <VALUE>20.10.1-0066</VALUE>
            <DisplayValue>20.10.1-0066</DisplayValue>
          </PROPERTY>
        </INSTANCE>
      </VALUE.NAMEDINSTANCE>
    </SIMPLEREQ>
  </MESSAGE>
</CIM>';

- 查询

SELECT @xml.value(N'(/CIM/@CIMVERSION)[1]',N'nvarchar(max)') AS CIM_version
      ,@xml.value(N'(/CIM/MESSAGE/@ID)[1]',N'nvarchar(max)') AS Message_Id
      ,@xml.value(N'(/CIM/MESSAGE/SIMPLEREQ/VALUE.NAMEDINSTANCE/INSTANCENAME/KEYBINDING/KEYVALUE/text())[1]',N'nvarchar(max)') AS Keybinding_Value
      ,prp.value(N'@NAME',N'nvarchar(max)') AS Prop_Name
      ,prp.value(N'(VALUE/text())[1]',N'nvarchar(max)') AS Prop_Value
      ,prp.value(N'(DisplayValue/text())[1]',N'nvarchar(max)') AS Prop_DisplayValue
FROM @xml.nodes(N'/CIM/MESSAGE/SIMPLEREQ/VALUE.NAMEDINSTANCE/INSTANCE/PROPERTY') AS A(prp);

结果

+-------------+------------+------------------+---------------------------+-------------------+-------------------+
| CIM_version | Message_Id | Keybinding_Value | Prop_Name                 | Prop_Value        | Prop_DisplayValue |
+-------------+------------+------------------+---------------------------+-------------------+-------------------+
| 2.0         | 4711       | RAID.Slot.1-1    | DriverVersion             | NULL              | NULL              |
+-------------+------------+------------------+---------------------------+-------------------+-------------------+
| 2.0         | 4711       | RAID.Slot.1-1    | KeyID                     | NULL              | NULL              |
+-------------+------------+------------------+---------------------------+-------------------+-------------------+
| 2.0         | 4711       | RAID.Slot.1-1    | SASAddress                | 5782BCB00C577600  | 5782BCB00C577600  |
+-------------+------------+------------------+---------------------------+-------------------+-------------------+
| 2.0         | 4711       | RAID.Slot.1-1    | ProductName               | PERC H310 Adapter | PERC H310 Adapter |
+-------------+------------+------------------+---------------------------+-------------------+-------------------+
| 2.0         | 4711       | RAID.Slot.1-1    | DeviceCardSlotType        | PCI Express x8    | PCI Express x8    |
+-------------+------------+------------------+---------------------------+-------------------+-------------------+
| 2.0         | 4711       | RAID.Slot.1-1    | DeviceCardManufacturer    | DELL              | DELL              |
+-------------+------------+------------------+---------------------------+-------------------+-------------------+
| 2.0         | 4711       | RAID.Slot.1-1    | PCISubDeviceID            | 1F4E              | 1F4E              |
+-------------+------------+------------------+---------------------------+-------------------+-------------------+
| 2.0         | 4711       | RAID.Slot.1-1    | PCIDeviceID               | 73                | 73                |
+-------------+------------+------------------+---------------------------+-------------------+-------------------+
| 2.0         | 4711       | RAID.Slot.1-1    | PCISubVendorID            | 1028              | 1028              |
+-------------+------------+------------------+---------------------------+-------------------+-------------------+
| 2.0         | 4711       | RAID.Slot.1-1    | PCIVendorID               | 1000              | 1000              |
+-------------+------------+------------------+---------------------------+-------------------+-------------------+
| 2.0         | 4711       | RAID.Slot.1-1    | Function                  | 0                 | 0                 |
+-------------+------------+------------------+---------------------------+-------------------+-------------------+
| 2.0         | 4711       | RAID.Slot.1-1    | Device                    | 0                 | 0                 |
+-------------+------------+------------------+---------------------------+-------------------+-------------------+
| 2.0         | 4711       | RAID.Slot.1-1    | Bus                       | 1                 | 1                 |
+-------------+------------+------------------+---------------------------+-------------------+-------------------+
| 2.0         | 4711       | RAID.Slot.1-1    | ControllerFirmwareVersion | 20.10.1-0066      | 20.10.1-0066      |
+-------------+------------+------------------+---------------------------+-------------------+-------------------+

以上是关于使用SQL将XML文件解析为特定列的主要内容,如果未能解决你的问题,请参考以下文章

在 NodeJs 中使用 fast-xml-parser 将特定标签解析为数组

将 XML 解析为 sql 参数、datetime2 和位问题

SQL基础之XML

XML 解析在第 1 行第 9 列失败:DTD 被禁止

如何在 SQL 中查询特定文本的 xml 列

j2me:如何将字节数组解析为 xml,然后从该 XML 读取和显示特定数据