Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Querying XML data types which have xmlns node attributes

I have the following SQL query:

DECLARE @XMLDOC XML
SET @XMLDOC = '<Feed><Product><Name>Foo</Name></Product></Feed>'

SELECT  x.u.value('Name[1]', 'varchar(100)') as Name
from @XMLDOC.nodes('/Feed/Product') x(u)

This returns:

Name
----
Foo

However, if my <Feed> node has an xmlns attribute, then this doesn't return any results:

DECLARE @XMLDOC XML
SET @XMLDOC = '<Feed xmlns="bar"><Product><Name>Foo</Name></Product></Feed>'

SELECT  x.u.value('Name[1]', 'varchar(100)') as Name
from @XMLDOC.nodes('/Feed/Product') x(u)

Returns:

Name
----

This only happens if I have an xmlns attribute, anything else works fine.

Why is this, and how can I modify my SQL query to return results regardless of the attributes?

like image 893
Curtis Avatar asked May 09 '13 12:05

Curtis


People also ask

How do I query values in XML nodes?

You can retrieve multiple values from the rowset. For example, you can apply the value() method to the rowset returned by nodes() and retrieve multiple values from the original XML instance. The value() method, when applied to the XML instance, returns only one value.

How do I query XML data?

XML data can be queried using an SQL fullselect or with the SQL/XML query functions of XMLQUERY and XMLTABLE. The XMLEXISTS predicate can also be used in SQL queries on XML data.

How do I select a specific XML node in SQL Server?

You should use the query() Method if you want to get a part of your XML. If you want the value from a specific node you should use value() Method. Update: If you want to shred your XML to multiple rows you use nodes() Method.

How do I query XML data in SQL Server?

SQL Server provides the XQuery feature to querying XML data type or querying with the XML column with the XPATH. Using XQuery, users can Insert, Update and Delete with the XML nodes and node values in an XML column.


2 Answers

If your XML document has XML namespaces, then you need to consider those in your queries!

So if your XML looks like your sample, then you need:

-- define the default XML namespace to use
;WITH XMLNAMESPACES(DEFAULT 'bar')
SELECT   
    x.u.value('Name[1]', 'varchar(100)') as Name
from 
    @XMLDOC.nodes('/Feed/Product') x(u)

Or if you prefer to have explicit control over which XML namespace to use (e.g. if you have multiple), use XML namespace prefixes:

-- define the XML namespace 
;WITH XMLNAMESPACES('bar' as b)
SELECT   
    x.u.value('b:Name[1]', 'varchar(100)') as Name
from 
    @XMLDOC.nodes('/b:Feed/b:Product') x(u)
like image 143
marc_s Avatar answered Sep 17 '22 21:09

marc_s


As well as the XMLNAMESPACES solution, you can also use the hideously bulky local-name syntax...

DECLARE @XMLDOC XML
SET @XMLDOC = '<Feed xmlns="bar"><Product><Name>Foo</Name></Product></Feed>'

SELECT  x.u.value('*[local-name() = "Name"][1]', 'varchar(100)') as Name
from @XMLDOC.nodes('/*[local-name() = "Feed"]/*[local-name() = "Product"]') x(u)
like image 26
El Ronnoco Avatar answered Sep 20 '22 21:09

El Ronnoco