在SQL SERVER中获取XML结构

时间:2014-08-08 13:01:03

标签: sql-server xml

我有一个XML变量,例如

DECLARE @xml XML = 
'<A>
 <AA>aa</AA>
 <AB>
   <ABA>aba</ABA>
 </AB>
</A>
<B>b</B>
<C>
 <CA>ca</CA>
</C>

我想用一个VARCHAR kolumn获取这个XML表的结构:

structure (VARCHAR)
--------------------
'A/AA'
'A/AB/ABA'
'B'
'C/CA'.

我不需要在节点中获取文本 - 我只需要结构。 XML变量可以不同(我不知道节点数,节点名称等)。

变量@xml可以没有ROOT元素。

我尝试了很多.value()或.nodes()的组合,但它没有用。 最好的结果给我一个操作:

SELECT
    grandparent.gname.value('fn:local-name(.)', 'VARCHAR(MAX)'),
    parent.pname.value('fn:local-name(.)', 'VARCHAR(MAX)'),
    child.cname.value('fn:local-name(.)', 'VARCHAR(MAX)')
FROM
    @xml.nodes('*') AS grandparent(gname)
CROSS APPLY
    grandparent.gname.nodes('*') AS parent(pname)
CROSS APPLY
    parent.pname.nodes('*') AS child(cname)

它给了我A / AB / ABA&#39;但如果我不知道节点和节点名称的数量,那么我继续是没用的。

1 个答案:

答案 0 :(得分:2)

使用递归CTE一次提取一级节点。锚点部分提取根节点,query('*')获取找到的每个节点的子节点。 exist('*')用于过滤掉递归期间创建的中间行。递归部分与锚点相同,只是它使用SubNodes中提供的XML。

declare @xml xml = 
'<A>
 <AA>aa</AA>
 <AB>
   <ABA>aba</ABA>
 </AB>
</A>
<B>b</B>
<C>
 <CA>ca</CA>
</C>';

with C as
(
  select T.X.value('local-name(.)', 'nvarchar(max)') as Structure,
         T.X.query('*') as SubNodes,
         T.X.exist('*') as HasSubNodes
  from @xml.nodes('*') as T(X)
  union all 
  select C.structure + N'/' + T.X.value('local-name(.)', 'nvarchar(max)'),
         T.X.query('*'),
         T.X.exist('*')
  from C
    cross apply C.SubNodes.nodes('*') as T(X)
)
select C.Structure
from C
where C.HasSubNodes = 0;

结果:

Structure
---------
B
C/CA
A/AA
A/AB/ABA