SSIS XML 无类型任务 XML

SSIS XML Task with Untyped XML

我对从 XML 数据源加载数据到 SQL 服务器还很陌生,但我过去曾成功地使用格式正确的 XML 数据源。我有一个 Web 服务,该服务正在通过第三方解决方案的 SSIS 调用以获取数据。此 Web 服务吐出如下数据:

<?xml version="1.0" encoding="utf-16"?>
<EpsTableEx xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <ErrorString />
  <ErrorNum>1</ErrorNum>
  <Data>
    <ArrayOfString>
      <string>ObjectId</string>
      <string>Form_Type</string>
      <string>Owner</string>
      <string>CompletedDate</string>
      <string>Delivered</string>
      <string>Name</string>
      <string>EventID</string>
    </ArrayOfString>
    <ArrayOfString>
      <string>183122</string>
      <string>Form1</string>
      <string>91b</string>
      <string>2015-03-02</string>
      <string>2015-04-22</string>
      <string>Onboarding</string>
      <string>21966</string>
    </ArrayOfString>
    <ArrayOfString>
      <string>183152</string>
      <string>Form1</string>
      <string>2879d</string>
      <string>2015-03-02</string>
      <string>2015-04-22</string>
      <string>Onboarding</string>
      <string>21967</string>
    </ArrayOfString>
  </Data>
</EpsTableEx>

第一个 ArrayOfString 是 header 列,而不是每个元素都是 header.

在另一个具有正确格式的 XML 网络服务的包中,我正在使用 XML 任务编辑器通过 XPATH 操作深入到数据级别,这对我不起作用这里。这导致 ArrayOfString 和 String 被剥离,所有数据连接在一起。

我试过:

  1. 将 XPATH 操作更改为 XML 路径的不同级别但没有成功。
  2. 改变 XSD 文件试图强制它认为 ArrayOfString 标记中的文本将是要插入到 table 中的文本,然后稍后解析它,但没有数据通过.
  3. 更改 XSD 文件,使定义的字段具有 String1、String2 等,希望它将映射到每个项目的通用字符串标签。

我正在使用 SQL Server 2014 和 Data Tools 构建 SSIS 包。

编辑: 目标是在 SSIS 中有一个解决方案,可以 运行 每晚。

编辑2: 数据将被加载到 table 中,如下所示:

CREATE TABLE [dbo].[FormXML](

[ObjectID] [nvarchar](255) NULL,
[Form_Type] [nvarchar](255) NULL,
[Owner] [nvarchar](255) NULL,
[CompletedDate] [nvarchar](255) NULL,
[Delivered] [nvarchar](255) NULL,
[Name] [nvarchar](255) NULL,
[EventID] [nvarchar](255) NULL,
[ADD_DTTM] [datetime] NULL DEFAULT (getdate()))

我不关心 ErrorString 或 ErrorNum 节点。我修改了建议的 XML 查询以使用执行 SQL 任务将数据插入 table。

在 SSIS 中放入变量的 XML 是 +400k 个字符。我在网上看到,根据这篇文章 (http://www.sqlservercentral.com/articles/SQL+Server/97947/),字符串变量有 2GB 的限制。我怀疑这是我的问题,如果我可以将 XML 从 Web 服务加载到 XML 变量而不是字符串变量中,我就不会遇到这个问题。

假设这个 XML 携带一个带有数据行的 "table" 我建议不要从第一个块中获取列名。他们可能是"hard coded":

只需将其粘贴到一个空的 SQL 查询 window 中并执行。根据您的需要进行调整...

declare @x XML='<EpsTableEx xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <ErrorString />
  <ErrorNum>1</ErrorNum>
  <Data>
    <ArrayOfString>
      <string>ObjectId</string>
      <string>Form_Type</string>
      <string>Owner</string>
      <string>CompletedDate</string>
      <string>Delivered</string>
      <string>Name</string>
      <string>EventID</string>
    </ArrayOfString>
    <ArrayOfString>
      <string>183122</string>
      <string>Form1</string>
      <string>91b</string>
      <string>2015-03-02</string>
      <string>2015-04-22</string>
      <string>Onboarding</string>
      <string>21966</string>
    </ArrayOfString>
    <ArrayOfString>
      <string>183152</string>
      <string>Form1</string>
      <string>2879d</string>
      <string>2015-03-02</string>
      <string>2015-04-22</string>
      <string>Onboarding</string>
      <string>21967</string>
    </ArrayOfString>
  </Data>
</EpsTableEx>';

SELECT ArrayOfString.block.value('string[1]','int') AS ObjectId
      ,ArrayOfString.block.value('string[2]','varchar(max)') AS Form_Type
      ,ArrayOfString.block.value('string[3]','varchar(max)') AS [Owner]
      ,ArrayOfString.block.value('string[4]','date') AS CompletedDated
      ,ArrayOfString.block.value('string[5]','date') AS Delivered
      ,ArrayOfString.block.value('string[6]','varchar(max)') AS [Name]
      ,ArrayOfString.block.value('string[7]','int') AS EventID
FROM @x.nodes('/EpsTableEx/Data/ArrayOfString[position()>1]') AS ArrayOfString(block)

我使用 2 个不同的变量解决了这个问题。我将 Web 服务的 XML 输出输入到一个字符串变量中,我们称它为 String1。然后我创建了另一个变量,称为 String2,并创建了一个表达式来将 String1 格式化为可用的 XML 字符串。

我下面的表达式替换了“\n”、“\r”和“xmlns=\”http://Eprise\“”的所有实例,以正确设置字符串格式。然后我使用 SUBSTRING 表达式只获取数据标签中字符串的移植。 FINDSTRING 位于数据标记开始的位置,LEN 帮助找到字符串的实际长度。

replace(
    replace(
        replace(
            substring(@[User::String1], 
                      FINDSTRING( @[User::String1] , "<Data", 1) , 
                      LEN( 
                        substring(@[User::String1], 
                                  FINDSTRING( @[User::String1] , 
                                            "<Data", 
                                            1),
                                  LEN(@[User::String1])
                                  )
                        ) -13 
                    )
            ,"\n","")
        ,"\r","")
    ," xmlns=\"http://Eprise\"","")

我必须在 String1 中填充一个至少 13 个字符的初始值,以便我可以 trim 结束 String1 以删除最后一个结束标记。我还需要初始值来包含文本“String2 to evaluate to true initially.

格式化 String2 后,我使用并执行 SQL 任务。我添加了一个参数,使用 String2 作为 NVARCHAR 类型的输入方向,名称为 0,长度为 2147483647,即 2 gb,SSIS 中字符串的最大值。

我将 SQL 查询从 @Shnugo 调整为:

declare @x as xml

set @x=?

insert into Database.dbo.Table ([ObjectID] ,[Form_Type],[Owner],[CompletedDate],[Delivered],[Name],[EventID])

SELECT block.value('string[1]', 'varchar(max)') AS ObjectId
    ,block.value('string[2]', 'varchar(max)') AS Form_Type
    ,block.value('string[3]', 'varchar(max)') AS OWNER
    ,block.value('string[4]', 'varchar(max)') AS CompletedDated
    ,block.value('string[5]', 'varchar(max)') AS Delivered
    ,block.value('string[6]', 'varchar(max)') AS NAME
    ,block.value('string[7]', 'varchar(max)') AS EventID
FROM @x.nodes('/Data/ArrayOfString[position()>1]') AS ArrayOfString(block)

那个?从我格式化的 XML 字符串参数中提取值,然后使用 XML 查询将数据插入 table。