带有无类型XML的SSIS XML任务

时间:2015-09-02 16:01:29

标签: sql xml ssis

我很擅长将数据从XML数据源加载到SQL Server中,但过去我已经成功使用了格式正确的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是列标题,而不是每个元素都是列标题。

在另一个包含格式正确的XML Web服务的包中,我使用XML任务编辑器通过XPATH操作进入数据级别,这对我来说不起作用。这导致ArrayOfString和String被剥离,并且所有数据被连接在一起。

我试过了:

  1. 将XPATH操作更改为XML路径的不同级别,但未成功。
  2. 更改XSD文件以试图强制它认为ArrayOfString标记中的文本是要插入表中的文本,然后再解析它,但没有数据通过。
  3. 将XSD文件更改为已定义字段的String1,String2等,希望它将映射到每个项目的通用字符串标记。
  4. 我正在使用SQL Server 2014和数据工具来构建SSIS包。

    修改: 目标是在SSIS中建立一个可以每晚运行的解决方案。

    EDIT2: 数据将加载到如下表格中:

    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任务将数据插入表中。

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

2 个答案:

答案 0 :(得分:1)

假设这个XML带有一个包含数据行的“表”,我建议不要从第一个块中获取列名。它们可能是“硬编码”的:

只需将其粘贴到一个空的SQL查询窗口并执行即可。根据您的需求进行调整......

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)

答案 1 :(得分:0)

我用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个字符的初始值,以便我可以修剪String1的结尾以删除最后一个结束标记。我还需要初始值来包含文本“String2以最初评估为真。

格式化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 String参数中提取值,然后使用XML Query将数据插入表中。