2012-07-25 35 views
2

組,我有以下XML文檔碎紙XML轉換成表格與T-SQL

<Root> 
    <Translation> 
     <Entry language ="ES" text = "Alsace"/> 
     <Entry language ="DE" text = "Elsass"/> 
     <Entry language ="EN" text = "Alsace"/> 
    </Translation> 
    <Translation> 
     <Entry language ="ES" text = "Brittany"/> 
     <Entry language ="DE" text = "Bretagne"/> 
     <Entry language ="EN" text = "Brittany"/> 
    </Translation> 
</Root> 

我需要它切碎成一個表,同時保留組。 因此,由於翻譯元素缺少任何id屬性,因此分組隱含在結構中。

表結果應該看起來像。

translation_id, lanuage, text 
--------------------------------- 
1,ES, Alsace 
1,DE, Elsass 
1,EN, Alsace 
2,ES , Brittany 
2,DE, Bretagne 
2,EN Brittany 

我曾嘗試過各種東西一樣

select newid(), 
( select rows.n.value('(@language)[1]', 'nvarchar(max)') 
    from @p.nodes('/Translation/Entry') rows(n) 
    ) 
from @p.nodes('/Translation') rows(n) 

但不能似乎得到的分組標識不使用某種循環。

謝謝

回答

2

沒有循環?好的...

select 
    rn, 
    t2.Entry.value('./@language','varchar(5)') ,  
    t2.Entry.value('./@text','varchar(50)')   
    from 
    (
     select 
      row_number() over (order by rows.n) as rn, 
      rows.n.query('.') as trans 
      from @p.nodes('/Root/Translation') rows(n) 
    ) trans  
     cross apply trans.nodes('Translation/Entry') as t2(Entry) 
0

最終解決了這個問題。不漂亮,我認爲必須有一種方法來做到這一點沒有循環。

declare @p xml 

set @p = 
'<Translation> 
<Entry language ="ES" text = "Alsace"/> 
<Entry language ="DE" text = "Elsass"/> 
<Entry language ="EN" text = "Alsace"/> 
</Translation> 
<Translation> 
<Entry language ="ES" text = "Aquitaine"/> 
<Entry language ="DE" text = "Aquitanien"/> 
<Entry language ="EN" text = "Aquitaine"/> 
</Translation> 
' 

declare @trans table (id int identity, t xml, [guid] varchar(255)) 
declare @result table ([guid] varchar(255), language char(2), [text] nvarchar(max)) 
declare @no int , @i int, @guid varchar(255), @t xml 

insert @trans 
(t, [guid]) 
select rows.n.query('.') as trans, newid() id 
from @p.nodes('/Translation') rows(n) 
set @no = scope_identity() 
set @i =1 

while @i <= @no 
begin 

select @guid = [guid], 
@t = t 
from @trans 
where id = @i 

insert @result 
([guid], language, [text]) 
select @guid, 
rows.n.value('(@language)[1]', 'nvarchar(max)'), 
rows.n.value('(@text)[1]', 'nvarchar(max)') 
from @t.nodes('/Translation/Entry') rows(n) 

set @i = @i +1 

end 


select * from @result 
0

我寫這段代碼,不是很好的工作,但它工作。

 declare @p xml 
    set @p = '<Root> 
    <Translation> 
    <Entry language ="ES" text = "Alsace"/> 
    <Entry language ="DE" text = "Elsass"/> 
    <Entry language ="EN" text = "Alsace"/> 
    </Translation> 
    <Translation> 
    <Entry language ="ES" text = "Brittany"/> 
    <Entry language ="DE" text = "Bretagne"/> 
    <Entry language ="EN" text = "Brittany"/> 
    </Translation> 
    </Root>' 

    Declare @n int 
    set @n = 1 -- counter for transaction nodes in xml 

    DECLARE @test xml -- to hold complete transaction node 

    While @n <= 2 -- while loop starts 
    BEGIN 
    SET @test = (select @p.query('/Root/Translation[sql:variable("@n")]')) 

    SELECT 
    @n as [Transaction], 
    a.b.value('Entry[1]/@language','varchar(10)') AS [Language], 
    a.b.value('Entry[1]/@text','varchar(10)') AS [Text] 
    FROM @test.nodes('Translation') a(b) 

    select @n as [Transaction] ,a.b.value('Entry[2]/@language','varchar(10)') AS [Language], 
    a.b.value('Entry[2]/@text','varchar(10)') AS [Text] 
    FROM @test.nodes('Translation') a(b) 

    SELECT 
    @n as [Transaction], 
    a.b.value('Entry[3]/@language','varchar(10)') AS [Language], 
    a.b.value('Entry[3]/@text','varchar(10)') AS [Text] 
    FROM @test.nodes('Translation') a(b) 


    SET @n = @n + 1 -- counter for transaction nodes in xml 

    END -- loop ended 

Output: 
    translation_id, lanuage, text 
    --------------------------------- 
    1,ES, Alsace 
    1,DE, Elsass 
    1,EN, Alsace 
    2,ES , Brittany 
    2,DE, Bretagne 
    2,EN Brittany