views:

36

answers:

2

Hi

A beginners question, hopefully easily answered. I've got an xml file I want to load into SQLServer 2008 and extract the useful informaiton.

I'm starting simple and just trying to extract the name (\gpx\name). The code I have is:

DECLARE @x xml;
SELECT @x = xCol.BulkColumn
FROM OPENROWSET (BULK 'C:\Data\EM.gpx', SINGLE_BLOB) AS xCol;
-- confirm the xml data is in @x
select @x as XML_Data
-- try and get the name of the gpx section
SELECT 
     c.value('name[1]', 'varchar(200)') as Name
from @x.nodes('gpx') x(c)

Below is a heavily shortened version of the xml file:

<?xml version="1.0" encoding="utf-8"?>
<gpx xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" version="1.0" creator="Groundspeak Pocket Query" xsi:schemaLocation="http://www.topografix.com/GPX/1/0 http://www.topografix.com/GPX/1/0/gpx.xsd http://www.groundspeak.com/cache/1/0 http://www.groundspeak.com/cache/1/0/cache.xsd" xmlns="http://www.topografix.com/GPX/1/0"&gt;
  <name>EM</name>
  <desc>Geocache file generated by Groundspeak</desc>
  <author>Groundspeak</author>
  <email>[email protected]</email>
  <time>2010-03-24T14:01:36.4931342Z</time>
  <keywords>cache, geocache, groundspeak</keywords>
  <wpt lat="51.2586" lon="-2.213067">
    <time>2008-03-30T07:00:00Z</time>
    <name>GC1APHM</name>
    <desc>Sandman's Noble Hoard by Sandman1973, Unknown Cache (2/3)</desc>
    <groundspeak:cache id="832000" available="True" archived="False" xmlns:groundspeak="http://www.groundspeak.com/cache/1/0"&gt;
      <groundspeak:name>Sandman's Noble Hoard</groundspeak:name>
      <groundspeak:placed_by>Sandman1973</groundspeak:placed_by>
    </groundspeak:cache>
  </wpt>
</gpx>

If the first two lines are replaced with just:

<gpx>

the above example works correctly, however I then can't access groundspeak:name (/gpx/wpt/groundspeak:cache/groundspeak:name), so my guess its a problem with the namespace.

Any help would be appriciated.

A: 

You must declare the namespace. Either like this:

WITH XMLNAMESPACES ('http://www.topografix.com/GPX/1/0' as ns1)
SELECT c.value('ns1:name[1]', 'varchar(200)') as Name
  FROM @x.nodes('ns1:gpx') x(c)

or like this:

SELECT c.value('declare namespace ns1="http://www.topografix.com/GPX/1/0"; ns1:name[1]', 'varchar(200)') as Name
  FROM @x.nodes('declare namespace ns1="http://www.topografix.com/GPX/1/0"; ns1:gpx') x(c)

To use the groundspeak namespace as well:

WITH XMLNAMESPACES ('http://www.topografix.com/GPX/1/0' as gpx, 'http://www.groundspeak.com/cache/1/0' as groundspeak)
SELECT c.value('(gpx:wpt/groundspeak:cache/groundspeak:name)[1]', 'nvarchar(max)')
  FROM @x.nodes('gpx:gpx') x(c)
erikkallen
Thanks for reply. What you posted didn't quite work for the WITH XMLNAMESPACES solution, all I got back was NULL, however I worked out name[1] needed to have the namespace reference, so it should have been: ;WITH XMLNAMESPACES ('http://www.topografix.com/GPX/1/0' as ns1) SELECT c.value('ns1:name[1]', 'varchar(200)') as Name FROM @x.nodes('ns1:gpx') x(c)
Brian
The second query I still can't get working. To start it references adventure works in your example - easy fix change but still no joy. Changing it to SELECT c.value('name[1]', 'varchar(200)') as Name FROM @x.nodes('declare namespace ns1="http://www.topografix.com/GPX/1/0"; ns1:gpx') x(c) returns one record containing NULL. Any attempt to alter name[1] just results in errors.
Brian
OK, I modded my answer to work. Accept, please.
erikkallen
Excellent, they all work nicely - Thanks.The additional bit about accessing the groundspeak:name was a very good addition showing how to mix the namespaces.
Brian
Just to complete the collection, the following seem to work for the second method to access the groundspeak:name :SELECT c.value('declare namespace groundspeak="http://www.groundspeak.com/cache/1/0"; groundspeak:name[1]', 'varchar(200)') as Name FROM @x.nodes('declare namespace gpx="http://www.topografix.com/GPX/1/0"; declare namespace groundspeak="http://www.groundspeak.com/cache/1/0"; gpx:gpx/gpx:wpt/groundspeak:cache') x(c) Thanks for the help
Brian
A: 

Got it, a few changes to erikkallen's answer and I've got it working:

;WITH XMLNAMESPACES ('http://www.topografix.com/GPX/1/0' as ns1) 
SELECT c.value('ns1:name[1]', 'varchar(200)') as Name 
  FROM @x.nodes('ns1:gpx') x(c) 

or

SELECT c.value('declare namespace ns1="http://www.topografix.com/GPX/1/0"; ns1:name[1]', 'varchar(200)') as Name 
  FROM @x.nodes('declare namespace ns1="http://www.topografix.com/GPX/1/0"; ns1:gpx') x(c) 

Thanks

Brian