2013-05-09 34 views
7

Tôi có truy vấn SQL sau:Truy vấn các kiểu dữ liệu XML có xmlns nút thuộc tính

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) 

này trả về:

Name 
---- 
Foo 

Tuy nhiên, nếu nút <Feed> tôi có một xmlns thuộc tính, sau đó doesn này không trả lại bất kỳ kết quả nào:

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) 

Trả về:

Name 
---- 

Điều này chỉ xảy ra nếu tôi có thuộc tính xmlns, mọi thứ khác hoạt động tốt.

Tại sao điều này và làm cách nào tôi có thể sửa đổi truy vấn SQL của mình để trả về kết quả bất kể thuộc tính?

Trả lời

8

Nếu tài liệu XML của bạn có không gian tên XML, sau đó bạn cần phải xem xét những người trong truy vấn của bạn!

Vì vậy, nếu XML của bạn trông giống như mẫu của bạn, sau đó bạn cần:

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

Hoặc nếu bạn muốn có quyền kiểm soát rõ ràng trên đó XML namespace sử dụng (ví dụ: nếu bạn có nhiều), sử dụng tiền tố namespace 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 Có cách nào đơn giản là bỏ qua các xmlns không? Tôi muốn chuyển đổi kiểu dữ liệu 'XML' thành một chuỗi, loại bỏ thuộc tính xmlns và sau đó bỏ nó trở lại ... – Curt

+0

Tôi thực sự không quan tâm đến không gian tên và đây là nguồn cấp dữ liệu của bên thứ ba với phiên bản trên xmlns URL, do đó, dễ bị thay đổi bên ngoài – Curt

+0

@Curt: không, khi không gian tên XML có trong XML của bạn, bạn không thể chỉ đơn giản là bỏ qua nó - bạn cần phải giải quyết nó. Nếu bạn chỉ có một không gian tên XML - sử dụng cách tiếp cận # 1 để định nghĩa nó là một không gian tên XML mặc định và cần phải khá đơn giản và dễ sử dụng –

1

Bạn có thể define namespaces như:

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

cũng như các giải pháp XMLNAMESPACES, bạn cũng có thể sử dụng cú pháp local-name hideously cồng kềnh ...

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 Cảm ơn vì giải pháp thay thế. Ngoài việc bị ghê tởm, điều này có nặng nề về hiệu suất không? – Curt

+0

Tôi sẽ tưởng tượng như vậy! Nó có lợi thế (hoặc có thể bất lợi? :)) không thực sự quan tâm đến không gian tên không giống như giải pháp 'XMLNAMESPACES' mà cụ thể nhắm vào một không gian tên đã cho. –

+0

Thêm vào đó - tôi thấy phân tích cú pháp XML trong SQLServer là khá chậm chạp bất kể ... Có lẽ tôi làm điều đó sai! –

Các vấn đề liên quan