I am using SQL Server 2008 and I want to retrieve XML elements and return the element itself and its attributes without any sub elements and without the text(). Eg the following XML has 4 nodes (doc, apple, b, banana):
<doc>
<apple type="bramley"> tasty <b>yum!</b> </apple>
<banana color="yellow" shape="bendy"> nice in smoothies </banana>
</doc>
I would like to return:
<doc/>
<apple type="bramley"/>
<b/>
<banana color="yellow" shape="bendy"/>
Eg doc should be returned without any sub-nodes and apple should be returned without the b sub-node. But the problem is, if I use the SQL Server nodes and query method I can't remove the sub-nodes. Using SQL Server 2008 the closest I have is:
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);
This gets the name of each node (using local-name) and the attributes of the node and returns:
Node Attr
---- ----
doc <xx />
apple <xx type="bramley" />
b <xx />
banana <xx color="yellow" shape="bendy" />
I realize I can process this result, convert Attr to varchar, replace xx by the Node column and convert back to XML. But is there an easier way without string manipulation?
PS: If it helps, I don't mind if the solution uses SQL Server 2008 or SQL Server 2012.
Usually you would use element construction with dynamic tag names, but SQL Server doesn't support this:
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);
As an XQuery Update alternative (tested with SQL Server 2012), we can fetch all nodes (with all contents) and delete their subnotes.
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);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With