SQL Server 2005“FOR XML PATH”具有相同名称的多个标记

时间:2009-03-23 11:54:18

标签: sql sql-server xml

我有一个像以下

的XML结构
<root>
    <person>
        <name>James</name>
        <description xsi:type="me:age">12</description>
        <description xsi:type="me:height>6 foot</description>
...

我必须退出像......这样的桌子。

姓名,年龄,身高

我正在尝试使用SQL 2005中的FOR XML路径和

这样的查询
SELECT
Name as 'name'
Age as 'description xsi:type="me:age"'
Height as 'description xsi:type="me:height"'
FOR XML PATH('person')

但它给我一个关于'description xsi'命名空间丢失的错误。有没有办法使用FOR XML PATH实现这一点。实际查询比这个例子复杂得多,需要花费很多精力才能改变。

由于

5 个答案:

答案 0 :(得分:5)

FOR XML PATH有时候有点困难(至少从我所知道的)。这可能会让你到达那里:

WITH XMLNAMESPACES('uri' as xsi)    
SELECT    
'me:age'     AS 'description/@xsi:type'    
,age         AS 'description'    
,name        AS 'name'   
,'me:height' AS 'description/@xsi:type'    
,height      AS 'description'    
FROM #test    
FOR XML PATH('person')

产地:

<person xmlns:xsi="uri">
  <description xsi:type="me:age">32</description>
  <name>Alice</name>
  <description xsi:type="me:height">6 Foot</description>
</person>
<person xmlns:xsi="uri">
  <description xsi:type="me:age">24</description>
  <name>Bob</name>
  <description xsi:type="me:height">5 Feet 5 Inches</description>
</person>

答案 1 :(得分:1)

我认为使用FOR XML PATH处理具有相同名称的兄弟节点是不可能的。

我能够使用FOR XML EXPLICIT生成您的架构。

输出不是有效的XML,因为它不包含xsi命名空间的定义,但它确实符合您的规范:

create table #test
(id int identity
,name varchar(50)
,age int
,height varchar(20))

insert #test (name,age,height)
select 'Alice',32,'6 feet one inch'
union select 'Bob',30,'5 feet 10 inches'
union select 'Charles',23,'6 feet two inch'

SELECT 1         AS Tag
       ,NULL     AS Parent
       ,''       AS [root!1]
       ,null     AS [person!2!name!ELEMENT]
       ,null     AS [description!3]
       ,null     AS [description!3!xsi:type]  
       ,null     AS [description!4]
       ,null     AS [description!4!xsi:type]     
UNION ALL
SELECT 2         AS Tag
       ,1        AS Parent
       ,null
       ,name
       ,null
       ,null 
       ,null
       ,null    
FROM #test
UNION ALL
SELECT 3         AS Tag
       ,2        AS Parent
       ,null       
       ,name     
       ,age      
       ,'me:age' 
       ,null
       ,null 
FROM #test
UNION ALL
SELECT 4         AS Tag
       ,2        AS Parent
       ,null       
       ,name     
       ,null
       ,null
       ,height   
       ,'me:height'
FROM #test
order by [person!2!name!ELEMENT],Tag
FOR XML EXPLICIT

答案 2 :(得分:1)

一个很好的解决方案,类似于eddiegroves'但不需要重新排序同名兄弟姐妹{(3}}。

改编的代码示例(也是根据eddiegroves的回答修改):

WITH XMLNAMESPACES('uri' as xsi)
SELECT name AS 'person/name'
,   'me:age' AS 'person/description/@xsi:type'
,   age AS 'person/description'
,   '' AS 'person'
,   'me:height' AS 'person/description/@xsi:type'
,   height AS 'person/description'
,   '' AS 'person'
,   'me:weight' AS 'person/description/@xsi:type'
,   weight AS 'person/description'
FROM #test
FOR XML PATH('')

答案 3 :(得分:1)

<rt> 
  <A> 
    <B> 
      <C> 
        <D> 
          <E>a</E> 
          <F>b</F> 
          <G>c</G> 
        </D> 
    <D> 
          <E>x</E> 
          <F>y</F> 
          <G>z</G> 
        </D> 
      </C> 
    </B> 
  </A> 
</rt> 

- 标签打印后,我将以下字段添加到我的查询中以使标记关闭&amp;开

,(SELECT * FROM          
    (SELECT '' AS 'text()'           
    ) l         
    FOR XML PATH(''),type) as 'A/B/C' 

- 使用借来的代码

答案 4 :(得分:0)

我们需要制作这样的东西......

<rt>
  <A>
    <B>
      <C>
        <D>
          <E>a</E>
          <E>b</E>
          <E>c</E>
          <E>d</E>
        </D>
      </C>
    </B>
  </A>
</rt>

它有重复的E元素。

我们用下面的t-sql做了。

select 
    '' as "A/B/C/D"
    ,
    (
        SELECT * FROM 
        (
              SELECT 'a' AS 'text()'
        UNION SELECT 'b' AS 'text()'
        UNION SELECT 'c' AS 'text()'
        UNION SELECT 'd' AS 'text()'
        ) l
        FOR XML PATH('E'),type 
    ) as 'A/B/C/D'

from [Case]
where [Case].CaseRef = 'YOUR_PKEY' 
for xml path('rt')
go 

应该可以在xsi属性中查找...