【问题标题】:How to import XML to SQL Server when base nodes repeat基节点重复时如何将 XML 导入 SQL Server
【发布时间】:2017-05-01 12:47:48
【问题描述】:

我正在将生成的 XML 文件导入 SQL Server 数据库。它工作正常,但现在我需要来自重复节点的额外信息,但我无法弄清楚。我正在使用带有SQLXMLBulkLoad.SQLXMLBulkload.4.0 的VBScript 来导入文件。每个文件中有很多<file>节点,这里以简化为例:

<?xml version="1.0" encoding="UTF-8"?>
<samp_catalog version='1.0'>
  <file>
    <name>123.wav</name>
    <xyz>
      <a_samp>
        <a_one>1</a_one>
        <a_two>2</a_two>
        <a_three>3</a_three>
      </a_samp>
      <b_samp version='2.0'>
        <b_four>sample</b_four>
        <b_five>sample</b_five>
        <b_six>sample</b_six>
      </b_samp>
      <c_samp version='1.0'>
        <c_entry>
          <total_size>0</total_size>
          <sig>sample</sig>
          <type>SAMPLE</type>
          <data_size>256</data_size>
          <data encoding='string'></data>
        </c_entry>
      </c_samp>
      <c_samp version='1.0'>
        <c_entry>
          <total_size>0</total_size>
          <sig>sample</sig>
          <type>PHONE</type>
          <data_size>256</data_size>
          <data encoding='string'>15555551212</data>
        </c_entry>
      </c_samp>
      <c_samp version='1.0'>
        <c_entry>
          <total_size>0</total_size>
          <sig>sample</sig>
          <type>OTHER_SAMPLE</type>
          <data_size>256</data_size>
          <data encoding='string'></data>
        </c_entry>
      </c_samp>
    </xyz>
  </file>
</samp_catalog>

没有重复的c_samp 节点,架构很简单:

<xsd:schema xmlns:xsd = "http://www.w3.org/2001/XMLSchema" xmlns:sql = "urn:schemas-microsoft-com:mapping-schema">
  <xsd:element name = "samp_catalog" sql:is-constant = "1">
    <xsd:complexType>
      <xsd:sequence>
        <xsd:element name = "file" sql:relation = "files" maxOccurs = "unbounded">
          <xsd:complexType>
            <xsd:sequence>
              <xsd:element name = "name" type = "xsd:string" sql:field = "name" />
              <xsd:element name = "xyz" sql:is-constant = "1">
                <xsd:complexType>
                  <xsd:sequence>
                    <xsd:element name = "a_samp" sql:is-constant = "1">
                      <xsd:complexType>
                        <xsd:sequence>
                          <xsd:element name = "a_one" type = "xsd:integer" sql:field = "a_one" />
                          <xsd:element name = "a_two" type = "xsd:integer" sql:field = "a_two" />
                          <xsd:element name = "a_three" type = "xsd:integer" sql:field = "a_three" />
                        </xsd:sequence>
                      </xsd:complexType>
                    </xsd:element>
                    <xsd:element name = "b_samp" sql:is-constant = "1">
                      <xsd:complexType>
                        <xsd:sequence>
                          <xsd:element name = "b_four" type = "xsd:string" sql:field = "b_four" />
                          <xsd:element name = "b_five" type = "xsd:string" sql:field = "b_five" />
                          <xsd:element name = "b_six" type = "xsd:string" sql:field = "b_six" />
                        </xsd:sequence>
                      </xsd:complexType>
                    </xsd:element>
                  </xsd:sequence>
                </xsd:complexType>
              </xsd:element>
            </xsd:sequence>
          </xsd:complexType>
        </xsd:element>
      </xsd:sequence>
    </xsd:complexType>
  </xsd:element>
</xsd:schema>

重要的是第二个data 元素(type PHONE),但也可以将它们全部导入。我已经尝试在架构中定义所有 3 个 c_samps 并仅为指定的 data 元素定义一个 sql:field 并为所有元素定义它,但是对于 c_samp 下的所有内容,导入总是导致 NULL元素。

如何将重复节点导入数据库?

【问题讨论】:

  • 这个问题解决了吗?您需要进一步的帮助吗?请给我一个提示:如果这个问题得到解决,您将非常好心,在(最佳)答案的投票计数器下方勾选接受检查(可能是您自己的答案)。这将 1) 将此问题标记为已解决 2) 让追随者更容易找到最佳解决方案 3) 向回答者支付积分和 4) 向您支付积分。一旦您自己越过了 15 点边界,您还被要求对贡献进行投票。这是说谢谢的方式。编码快乐!

标签: sql-server xml import xsd schema


【解决方案1】:

我会在 SQL-Server 中编写一个 存储过程,然后传递 XML 原样。使用 SQL Server 的能力在没有架构的情况下读取 XML。

以下代码将从给定的 XML 中提取所有信息。

做一些类似的事情

CREATE dbo.ImportMyXML(@xml XML)
AS
BEGIN
    --Code here
END
GO

BEGIN END 中编写此查询(注释掉INSERT INTO 以测试查询结果:

--INSERT INTO YourTargetTable(col1,col2,col3,...)
SELECT @xml.value(N'(/samp_catalog/file/name/text())[1]',N'nvarchar(max)') AS name
      ,a_samp.value(N'(*/text())[1]',N'nvarchar(max)') AS a_one
      ,a_samp.value(N'(*/text())[2]',N'nvarchar(max)') AS a_two
      ,a_samp.value(N'(*/text())[3]',N'nvarchar(max)') AS a_three

      ,b_samp.value(N'@version',N'nvarchar(max)') AS b_version
      ,b_samp.value(N'(*/text())[1]',N'nvarchar(max)') AS b_one
      ,b_samp.value(N'(*/text())[2]',N'nvarchar(max)') AS b_two
      ,b_samp.value(N'(*/text())[3]',N'nvarchar(max)') AS b_three

      ,NodesWith_c_entry.value(N'(../@version)[1]',N'nvarchar(max)') AS c_version
      ,NodesWith_c_entry.value(N'(total_size/text())[1]','int') AS c_total_size
      ,NodesWith_c_entry.value(N'(sig/text())[1]','nvarchar(max)') AS c_sig
      ,NodesWith_c_entry.value(N'(type/text())[1]','nvarchar(max)') AS c_type
      ,NodesWith_c_entry.value(N'(data_size/text())[1]','int') AS c_data_size
      ,NodesWith_c_entry.value(N'(data/@encoding)[1]','nvarchar(max)') AS c_data_encoding
      ,NodesWith_c_entry.value(N'(data/text())[1]','nvarchar(max)') AS c_data_text

FROM @xml.nodes(N'samp_catalog/file/xyz') AS A(xyz)
OUTER APPLY xyz.nodes('a_samp') AS B(a_samp)
OUTER APPLY xyz.nodes('b_samp') AS C(b_samp)
OUTER APPLY xyZ.nodes('*/c_entry') AS D(NodesWith_c_entry);

使用给定的 XML,结果如下:

+---------+-------+-------+---------+-----------+--------+--------+---------+-----------+--------------+--------+--------------+-------------+-----------------+-------------+
| name    | a_one | a_two | a_three | b_version | b_one  | b_two  | b_three | c_version | c_total_size | c_sig  | c_type       | c_data_size | c_data_encoding | c_data_text |
+---------+-------+-------+---------+-----------+--------+--------+---------+-----------+--------------+--------+--------------+-------------+-----------------+-------------+
| 123.wav | 1     | 2     | 3       | 2.0       | sample | sample | sample  | 1.0       | 0            | sample | SAMPLE       | 256         | string          | NULL        |
+---------+-------+-------+---------+-----------+--------+--------+---------+-----------+--------------+--------+--------------+-------------+-----------------+-------------+
| 123.wav | 1     | 2     | 3       | 2.0       | sample | sample | sample  | 1.0       | 0            | sample | PHONE        | 256         | string          | 15555551212 |
+---------+-------+-------+---------+-----------+--------+--------+---------+-----------+--------------+--------+--------------+-------------+-----------------+-------------+
| 123.wav | 1     | 2     | 3       | 2.0       | sample | sample | sample  | 1.0       | 0            | sample | OTHER_SAMPLE | 256         | string          | NULL        |
+---------+-------+-------+---------+-----------+--------+--------+---------+-----------+--------------+--------+--------------+-------------+-----------------+-------------+

【讨论】:

    【解决方案2】:

    到目前为止,我还没有找到我想要做的事情的答案,但这是我现在正在使用的解决方法。在 VBScript 中,使用Microsoft.XMLDOM 加载文件后,我循环遍历文件并找到所有文本值为PHONEtype 节点,然后创建一个新元素并将其附加到b_samp 及其兄弟data' s 文本值。

    VBScript:

    Set nodes = xmlFile.selectNodes("//type")
    For Each node in nodes
      If node.text = "PHONE" Then
        Set phoneNode = xmlFile.CreateElement("phone")
    
        For Each child in node.ParentNode.ChildNodes
          If child.nodeName = "data" Then phoneNode.text = child.text
        Next
    
        For Each child in node.ParentNode.ParentNode.ParentNode.ChildNodes
          If child.nodeName = "b_samp" Then child.appendChild phoneNode
        Next
      End If
    Next
    

    然后使用新名称保存文件以保持原始文件不变,并使用新架构导入它,并在 b_six 元素之后添加此行:

    <xsd:element name = "phone" type = "xsd:string" sql:field = "phone" />
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-05-26
      • 2023-03-16
      • 1970-01-01
      • 2012-07-15
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多