For this xml (in a SQL 2005 XML column):
<doc>
<a>1</a>
<b ba="1" bb="2" bc="3" />
<c bd="3"/>
<doc>
I'd like to be able to retrieve the names of the attributes (ba, bb, bc, bd) rather than the values inside SQL Server 2005. Well, XPath certainly allows this with name() but SQL doesn't support that. This is my chief complaint with using XML in SQL; you have to figure out which parts of the XML/Xpath/XQuery spec are in there.
The only way I can think of to do this is to build a CLR proc that loads the XML into an XML Document (iirc) and runs the XPath to extract the names of the nodes. I'm open to suggestions here.
DECLARE @xml as xml
DECLARE @path as varchar(max)
DECLARE @index int, @count int
SET @xml =
'<doc>
<a>1</a>
<b ba="1" bb="2" bc="3" />
<c bd="3"/>
</doc>'
SELECT @index = 1
SET @count = @xml.query('count(/doc/b/@*)').value('.','int')
WHILE @index <= @count
BEGIN
SELECT @xml.value('local-name((/doc/b/@*[sql:variable("@index")])[1])', 'varchar(max)')
SET @index = @index + 1
END
for element 'b'
it returns
You can build a loop to get attributes for each element in the xml.
BTW
The XML in your sample should be closed at closing doc tag.
DECLARE @xml as xml
SET @xml =
'<doc>
<a>1</a>
<b ba="1" bb="2" bc="3" />
<c bd="3"/>
</doc>'
SELECT DISTINCT
CAST(Attribute.Name.query('local-name(.)') AS VARCHAR(100)) Attribute,
Attribute.Name.value('.','VARCHAR(100)') Value
FROM @xml.nodes('//@*') Attribute(Name)
Returns:
Attribute Value
ba 1
bb 2
bc 3
bd 3
this:
declare @xml as xml
set @xml =
'<doc>
<a>1</a>
<b ba="1" bb="2" bc="3" />
<c bd="3"/>
</doc>'
select @xml.query('
for $attr in /doc/b/@*
return local-name($attr)')
returns:
ba bb bc
Declare @xml Xml = '<doc><a>1</a><b ba="1" bb="2" bc="3" /><c bd="3"/></doc>'
Select n.value('local-name(.)', 'varchar(max)') from @xml.nodes('/doc/*/@*') a(n)
Returns
ba
bb
bc
bd