2014-03-04 126 views
2

我有工作代码可以从XML文件中选择几个值。问题是我有多个同名的节点。XML到SQL - 选择具有相同名称的多个节点

这里是XML的一个片段:

<wd:Report_Data xmlns:wd="urn:com.workday.report/Countries_and_Their_Address_Components_Summary"> 
    <wd:Report_Entry> 
    <wd:Country wd:Descriptor="Afghanistan"> 
     <wd:ID wd:type="WID">db69b722446c11de98360015c5e6daf6</wd:ID> 
     <wd:ID wd:type="ISO_3166-1_Alpha-2_Code">AF</wd:ID> 
     <wd:ID wd:type="ISO_3166-1_Alpha-3_Code">AFG</wd:ID> 
     <wd:ID wd:type="ISO_3166-1_Numeric-3_Code">4</wd:ID> 
    </wd:Country> 
    <wd:Address_Format_Type wd:Descriptor="Basic"> 
     <wd:ID wd:type="WID">4516bf435611423ea4ee72fa842572a0</wd:ID> 
    </wd:Address_Format_Type> 
    <wd:Local>1</wd:Local> 
    <wd:Address_Components> 
     <wd:Address_Component wd:Descriptor="Address Line 1 - Local"> 
     <wd:ID wd:type="WID">12d859b8df024175a111da2e088250fb</wd:ID> 
     <wd:ID wd:type="Address_Component_Type_ID">ADDRESS_LINE_1_LOCAL</wd:ID> 
     </wd:Address_Component> 
     <wd:Order>a</wd:Order> 
     <wd:Required>0</wd:Required> 
    </wd:Address_Components> 
    <wd:Address_Components> 
     <wd:Address_Component wd:Descriptor="Address Line 2 - Local"> 
     <wd:ID wd:type="WID">85a6ab9412c44dd9a71a7e4760bf17fb</wd:ID> 
     <wd:ID wd:type="Address_Component_Type_ID">ADDRESS_LINE_2_LOCAL</wd:ID> 
     </wd:Address_Component> 
     <wd:Order>b</wd:Order> 
     <wd:Required>0</wd:Required> 
    </wd:Address_Components> 

我的SQL如下:

declare @inputxml table (x xml) 

insert @inputxml 
select x 
from OPENROWSET(BULK 'C:\ParallelTool\addcomp.xml', SINGLE_BLOB) As T(x) 

;WITH XMLNAMESPACES(DEFAULT 'urn:com.workday.report/Countries_and_Their_Address_Components_Summary') 
    select 
     xmldata.[ISO], xmldata.[Component 1], xmldata.[Component 2], xmldata.[Required] 
    into dbo.WD 
    from @inputxml 
    cross apply (
     select 
      [ISO] = xmldata.value('(Country/ID)[3]', 'VARCHAR(MAX)'), 
      [Component 1] = xmldata.value('(Address_Components/Address_Component/ID)[2]', 'VARCHAR(MAX)'), 
      [Component 2] = xmldata.value('(Address_Components/Address_Component/ID)[2]', 'VARCHAR(MAX)'), 
      [Required] = xmldata.value('(Address_Components/Required)[1]', 'INT') 
     from x.nodes('/Report_Data/Report_Entry') Z1(xmldata) 
    ) xmldata 

如果我不能得到我需要的是[分量2]。我希望基本上选择文件中的所有“Address_Component_Type_ID”,但它们全部命名相同,并在命名相同的其他节点下。我如何在我的SQL中指定获取所有组件类型?感谢您的期待!

回答

3

取决于你想做的事......如果你知道有要抢恰好2“Address_Components”,您可以修改您的查询,像这样的内容:

;WITH XMLNAMESPACES(DEFAULT 'urn:com.workday.report/Countries_and_Their_Address_Components_Summary') 
    select 
     xmldata.[ISO], xmldata.[Component 1], xmldata.[Component 2], xmldata.[Required] 
    from @inputxml 
    cross apply (
     select 
      [ISO] = xmldata.value('(Country/ID)[3]', 'VARCHAR(MAX)'), 
      [Component 1] = xmldata.value('(Address_Components/Address_Component/ID)[2]', 'VARCHAR(MAX)'), 
      [Component 2] = xmldata.value('(Address_Components[2]/Address_Component/ID)[2]', 'VARCHAR(MAX)'), 
      [Required] = xmldata.value('(Address_Components/Required)[1]', 'INT') 
     from x.nodes('/Report_Data/Report_Entry') Z1(xmldata) 
    ) xmldata 

而结果是这样的:

ISO Component 1    Component 2    Required 
----- ------------------------- ------------------------- ----------- 
AFG ADDRESS_LINE_1_LOCAL  ADDRESS_LINE_2_LOCAL  0 

但是,如果可以有任意数量的“Address_Components”,并要他们抢为单独的记录,你可以重写你的查询是这样的:

;WITH XMLNAMESPACES(DEFAULT 'urn:com.workday.report/Countries_and_Their_Address_Components_Summary') 
    select 
     [ISO] = Report_Entry.x.value('(Country/ID)[3]', 'VARCHAR(MAX)') 
     , [Component] = Address_Components.x.value('(Address_Component/ID)[2]', 'VARCHAR(MAX)') 
     , [Required] = Address_Components.x.value('(Required)[1]', 'INT') 
    from @inputxml 
    cross apply x.nodes('/Report_Data/Report_Entry') Report_Entry(x) 
    cross apply Report_Entry.x.nodes('./Address_Components') Address_Components (x) 

而结果是这样的:

ISO Component     Required 
----- ------------------------- ----------- 
AFG ADDRESS_LINE_1_LOCAL  0 
AFG ADDRESS_LINE_2_LOCAL  0 
+0

这是伟大的。这绝对是我所需要的正确方向迈出的一大步。你不能通过我链接的片段来判断,但我实际上有多个ISO。出于这个原因,当我使用交叉应用时,我将所有事情都放大到包含重复项。我只获得了299,000行(230个ISO的* 1300地址组件),而不是只有1300行。它本质上是交叉应用于每个节点,而不仅仅是当前节点中的节点。我一直在玩它没有运气一段时间。无论如何,它只能在目前的ISO内交叉应用? – bheltzel

+0

为了进一步澄清,它不完全重复。我错误地表达了它们 - 它们似乎是重复的。但是它所做的是抓取文件中的每个地址组件,并将其应用到每个ISO,我只需要来自相应ISO中的地址组件。 – bheltzel

+0

@bheltzel你是对的。我写交叉的方法适用于Address_Components,它从根中取出所有地址组件,而不仅仅是当前ISO元素的子元素。我现在纠正了它。如果它适合你,请将答案标为正确。 –

相关问题