Need help with SQL and XML

Hi,

I need some help on how to extract the values of XML elements.  The XML is formatted as follows:

declare @myxml as xml = '
<table class="genTbl closedTbl historicalTbl" id="curr_table">
	<thead>
		<tr>
			<th class="first left noWrap">Date</th>
			<th class="noWrap">Last</th>
			<th class="noWrap">Open</th>
			<th class="noWrap">High</th>
			<th class="noWrap">Low</th>
			<th class="noWrap">Change</th>
		</tr>
	</thead>
	<tbody>
		<tr>
			<td class="first left bold noWrap">Mar 19, 2014</td>
			<td class="redFont">3674.30</td>
			<td>3697.60</td>
			<td>3705.20</td>
			<td>3652.90</td>
			<td class="bold redFont">-0.62%</td>
		</tr>
		<tr>
			<td class="first left bold noWrap">Mar 18, 2014</td>
			<td class="greenFont">3697.20</td>
			<td>3652.70</td>
			<td>3701.90</td>
			<td>3639.90</td>
			<td class="bold greenFont">1.22%</td>
		</tr>
		<tr>
			<td class="first left bold noWrap">Mar 17, 2014</td>
			<td class="greenFont">3652.80</td>
			<td>3614.60</td>
			<td>3672.70</td>
			<td>3613.20</td>
			<td class="bold greenFont">1.07%</td>
		</tr>
	</tbody>
</table>'

Open in new window


How can I extract the data so it looks something like the following:

Date            Last            Open            High            Low                  Change
3/19/14      3674.30      3697.60            3705.20      3652.90            -0.62
etc.

thanks
LVL 1
yechanAsked:
Who is Participating?
 
Anthony PerkinsConnect With a Mentor Commented:
Here you go (change the data types as appropriate):
SELECT  T.C.value('(td)[1]', 'date') [Date],
        T.C.value('(td)[2]', 'smallmoney') [Last],
        T.C.value('(td)[3]', 'smallmoney') [Open],
        T.C.value('(td)[4]', 'smallmoney') [High],
        T.C.value('(td)[5]', 'smallmoney') [Low],
        T.C.value('(td)[5]', 'smallmoney') [Change]
FROM    @myxml.nodes('table/tbody/tr') T (C)

Open in new window

0
 
HooKooDooKuCommented:
To the best of my knowledge, XML is not a database, and therefore you can not use SQL to get anything out of an XML file.  Instead, you need an XML parser engine that accepts XPath statements... which are sort of like a query language for XML.

So if I were attempting to accomplish this, I would be starting with downloading MSXML 6.0:
http://www.microsoft.com/en-us/download/details.aspx?id=3988

Of course MSXML 6.0 is over 5 years old... so there might have been something else that has come along since I worked with SML that might allow SQL to access an XML file... but if so, I'm not aware of it.
0
 
awking00Commented:
This appears to define an HTML table. Is it stored as an xml column in a sql server database?
0
Cloud Class® Course: SQL Server Core 2016

This course will introduce you to SQL Server Core 2016, as well as teach you about SSMS, data tools, installation, server configuration, using Management Studio, and writing and executing queries.

 
Anthony PerkinsCommented:
You can use the SQL Server Xml Data Type Methods to retrieve the values.  For example if you wanted to get the first "class" attribute in the "thead" node you would do this;
SELECT @myxml.value('(table/thead/tr/th/@class)[1]', 'varchar(50)')
This returns:
first left noWrap
0
 
yechanAuthor Commented:
@ awking00:

For right now, I was hoping to be able to extract the values from the @myxml variable.  If you think to store the data in a xml data column just to get things going, I am cool with that too.

@Anthony:
Using the value() to extract the value within an element (i.e. SELECT @myxml.value('(table/tbody/tr/td)[1]', 'varchar(50)') AS myDate) I can extract the value of the first element, but how can I get a set of data like so:

Date            Last            Open            High            Low                  Change
3/19/14      3674.30      3697.60        3705.20      3652.90            -0.62
3/18/14      3697.20      3652.70        3701.90      3639.90             1.22
etc.

thank you.
0
 
Anthony PerkinsCommented:
You can use the nodes() method for that.  Let me know if you need an example.
0
 
yechanAuthor Commented:
Thanks Anthony.  I think I got it to work.


SELECT
      T.c.query('td[1]/text()') AS MyDate,
      T.c.query('td[2]/text()') AS MyLast
      etc
FROM  
      @myxml.nodes('/table/tbody/tr') T(c)
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.