6

我正在使用 SQL Server 2008,我想检索 XML 元素并返回元素本身及其属性,不带任何子元素且不带 text()。例如,以下 XML 有 4 个节点(doc、apple、b、banana):

<doc>
<apple type="bramley"> tasty <b>yum!</b> </apple>
<banana color="yellow" shape="bendy"> nice in smoothies </banana>
</doc>

我想返回:

<doc/>
<apple type="bramley"/>
<b/>
<banana color="yellow" shape="bendy"/>

例如doc应该返回没有任何子节点,而apple应该返回没有b子节点。但问题是,如果我使用 SQL Server 节点和查询方法,我无法删除子节点。使用 SQL Server 2008,我最接近的是:

declare @x xml = '<doc>
  <apple type="bramley"> tasty <b>yum!</b> </apple>
  <banana color="yellow" shape="bendy"> nice in smoothies </banana>
</doc>';

select 
  c.query('local-name(.)') as Node,
  c.query('for $e in . return <xx> {$e/@*} </xx>') as Attr
from @x.nodes('//*') as T(c);

这将获取每个节点的名称(使用本地名称)和节点的属性并返回:

Node    Attr
----    ----
doc     <xx />
apple   <xx type="bramley" />
b       <xx />
banana  <xx color="yellow" shape="bendy" />

我意识到我可以处理这个结果,将 Attr 转换为 varchar,用 Node 列替换 xx 并转换回 XML。但是没有字符串操作有没有更简单的方法?

PS:如果有帮助,我不介意该解决方案是使用 SQL Server 2008 还是 SQL Server 2012。

4

1 回答 1

1

通常您会使用带有动态标记名称的元素构造,但 SQL Server 不支持这一点:

declare @x xml = '<doc>
  <apple type="bramley"> tasty <b>yum!</b> </apple>
  <banana color="yellow" shape="bendy"> nice in smoothies </banana>
</doc>';

select 
  c.query('local-name(.)') as Node,
  c.query('for $e in . return element { local-name($e) } { $e/@* } </xx>') as Attr
from @x.nodes('//*') as T(c);

作为XQuery 更新替代方案(使用 SQL Server 2012 测试),我们可以获取所有节点(包含所有内容)并删除它们的子注释。

DECLARE @x xml = '<doc>test
  <apple type="bramley"> tasty <b>yum!</b> </apple>
  <banana color="yellow" shape="bendy"> nice in smoothies </banana>
</doc>';

-- Fetch all nodes
SET @x = @x.query('//*')
-- Delete all subnodes
SET @x.modify('delete /*/node()')

select 
  c.query('.') as NewNode
from @x.nodes('/*') as T(c);
于 2012-12-16T23:40:50.943 回答