2013-05-09 75 views
7

我有以下SQL查詢:查詢XML數據類型的屬性

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) 

這將返回:

Name 
---- 
Foo 

但是,如果我<Feed>節點有一個xmlns屬性,那麼這並未不會返回任何結果:

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) 

返回:

Name 
---- 

這隻會發生,如果我有xmlns屬性,其他任何工作正常。

這是爲什麼,我該如何修改我的SQL查詢以返回結果,而不考慮屬性?

回答

8

如果你的XML文檔的XML命名空間,則需要考慮那些在您的查詢!

所以,如果您的XML看起來像你的樣品,那麼你需要:

-- 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) 

或者,如果您願意讓在其XML命名空間來使用(例如,如果您有多個),使用XML命名空間前綴的明確控制:

-- 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) 
+0

+1有沒有簡單地忽略xmlns的方法?我試圖將'XML'數據類型轉換爲字符串,去掉xmlns屬性,然後將其轉換回來... – Curt 2013-05-09 13:38:31

+0

我真的不在乎命名空間,這是第三方提供的版本控制xmlns URL,因此很容易發生外部變化 – Curt 2013-05-09 13:39:13

+0

@Curt:不,當XML名稱空間存在於XML中時,不能簡單地忽略它 - 您需要處理它。如果您只有一個XML名稱空間 - 使用方法#1將其定義爲默認的XML名稱空間,並且該名稱空間應該相當簡單易用 – 2013-05-09 14:02:03

1

您可以define namespaces,如:

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) 
5

還有XMLNAMESPACES解決方案,您還可以使用令人髮指的笨重local-name語法...

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) 
+0

+1感謝您的替代解決方案。除了醜陋之外,這個表現還很重要嗎? – Curt 2013-05-09 13:40:42

+0

我會這麼想!它確實有優勢(或者可能缺點?:))實際上並不關心名稱空間,而不像專門針對給定名稱空間的'XMLNAMESPACES'解決方案。 – 2013-05-09 14:32:12

+0

除此之外 - 我發現SQLServer中的XML解析非常緩慢無論...也許我做錯了! – 2013-05-09 14:33:10