Return attribute nodes from multiple element nodes using SQL 2008 and Xquery

I have a table in SQL 2008 which contains one column as an xml data type.

This table has thousands of rows and for that xml column the xml data in that field would have a stucture like follows:

<client_info first_name="John" last_name="Doe">
<court date="08/01/2010">
<cs date="09/01/2010" />
<cs date="10/01/2010" />
</court>
<meeting date="08/05/2010">
<teacher date="08/06/2010" />
<teacher date="10/18/2010" />
</meeting>
</client>

How can I return, preferably as a single XML datagram, a document that has the value of every date attribute and the local-name of it's parent node bearing in mind this is just a simple XML example and there can and will be more levels to this document and it will need to be processed for each row on the table ideally returning a single XML datagram.

Any SQL/XML experts who can share a solution I would greatly appreciate it.
LVL 6
hyphenpipeAsked:
Who is Participating?
 
hyphenpipeConnect With a Mentor Author Commented:
Got it.

select      name = node.c.value('local-name(.)', 'varchar(75)')
            , date = node.c.value('@date', 'datetime')
 from @doc.nodes('//*[@*[local-name(.) = "date"]]') node(c)
 for xml auto

Thanks.

0
 
hyphenpipeAuthor Commented:
The best I have come up with so far is:

select      t.c.value('local-name(.)', 'varchar(75)')
            , date = t.c.value('@date', 'datetime')
 from table
 cross apply column.nodes('//*') t(c)
 where t.c.exist('//@*[local-name(.) = "date"]') = 1

But that returns every node name in for the XML document if at has at least one date.

I'd like to return on one shot just every date and its parent node name.
0
 
hyphenpipeAuthor Commented:
Also, I notice my XML is not well formed.

The starting element node should be <client... and not <client_info...

I think you get the rest.
0
 
hyphenpipeAuthor Commented:
As an update, here is what I have so far:

declare @doc xml
set @doc = '<client first_name="John" last_name="Doe">
<court date="08/01/2010">
<cs date="09/01/2010" />
<cs date="10/01/2010" />
</court>
<meeting date="08/05/2010">
<teacher date="08/06/2010" />
<teacher date="10/18/2010" />
</meeting>
</client>'

select @doc

select      name = node.c.value('local-name(.)', 'varchar(75)')
            , date = node.c.value('@date', 'datetime')
 from @doc.nodes('//*') node(c)
 where node.c.exist('//@*[local-name(.) = "date"]') = 1
 for xml auto

Doing so returns this:

<node name="client" />
<node name="court" date="2010-08-01T00:00:00" />
<node name="cs" date="2010-09-01T00:00:00" />
<node name="cs" date="2010-10-01T00:00:00" />
<node name="meeting" date="2010-08-05T00:00:00" />
<node name="teacher" date="2010-08-06T00:00:00" />
<node name="teacher" date="2010-10-18T00:00:00" />

But I would like to eliminate that first node (client) before returning the XML datagram.

Again, I will also need to process this for a large table with thousands of rows but just one XML column.
0
 
hyphenpipeAuthor Commented:
Figured out my own solution.
0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

All Courses

From novice to tech pro — start learning today.