使用 FOR XML PATH 时如何删除嵌套查询中的冗余命名空间

2024-04-02

UPDATE:我发现有一个针对此问题提出的 Microsoft Connect 项目here https://connect.microsoft.com/SQLServer/feedback/details/265956

使用时FOR XML PATH and WITH XMLNAMESPACES要声明默认命名空间,我将在使用 FOR XML 的嵌套查询的任何顶级节点中重复命名空间声明,我在网上偶然发现了一些解决方案,但我并不完全相信......

这是一个完整的例子

/*
drop table t1
drop table t2
*/
create table t1 ( c1 int, c2 varchar(50))
create table t2 ( c1 int, c2 int, c3 varchar(50))
insert t1 values 
(1, 'Mouse'),
(2, 'Chicken'),
(3, 'Snake');
insert t2 values
(1, 1, 'Front Right'),
(2, 1, 'Front Left'),
(3, 1, 'Back Right'),
(4, 1, 'Back Left'),
(5, 2, 'Right'),
(6, 2, 'Left')



;with XmlNamespaces( default 'uri:animal')
select 
    a.c2 as "@species"
    , (select l.c3 as "text()" 
       from t2 l where l.c2 = a.c1 
       for xml path('leg'), type) as "legs"
from t1 a
for xml path('animal'), root('zoo')

最好的解决方案是什么?


经过几个小时的绝望和数百次试验和错误后,我想出了以下解决方案。

当我想要时,我遇到了同样的问题just one xmlns属性,在root node only。但我也有一个非常困难的查询,有很多子查询和FOR XML EXPLICIT单纯的方法太麻烦了。所以是的,我想要方便FOR XML PATH在子查询中,也可以设置我自己的xmlns.

我好心借用了代码8kb's回答,因为它太好了。为了更好地理解,我对其进行了一些调整。这是代码:

DECLARE @Order TABLE (OrderID INT, OrderDate DATETIME)    
DECLARE @OrderDetail TABLE (OrderID INT, ItemID VARCHAR(1), Name VARCHAR(50), Qty INT)    
INSERT @Order VALUES (1, '2010-01-01'), (2, '2010-01-02')    
INSERT @OrderDetail VALUES (1, 'A', 'Drink',  5),
                           (1, 'B', 'Cup',    2),
                           (2, 'A', 'Drink',  2),
                           (2, 'C', 'Straw',  1),
                           (2, 'D', 'Napkin', 1)

-- Your ordinary FOR XML PATH query
DECLARE @xml XML = (SELECT OrderID AS "@OrderID",
                        (SELECT ItemID AS "@ItemID", 
                                Name AS "data()" 
                         FROM @OrderDetail 
                         WHERE OrderID = o.OrderID 
                         FOR XML PATH ('Item'), TYPE)
                    FROM @Order o 
                    FOR XML PATH ('Order'), ROOT('dummyTag'), TYPE)

-- Magic happens here!       
SELECT 1 AS Tag
      ,NULL AS Parent
      ,@xml AS [xml!1!!xmltext]
      ,'http://test.com/order' AS [xml!1!xmlns]
FOR XML EXPLICIT

Result:

<xml xmlns="http://test.com/order">
  <Order OrderID="1">
    <Item ItemID="A">Drink</Item>
    <Item ItemID="B">Cup</Item>
  </Order>
  <Order OrderID="2">
    <Item ItemID="A">Drink</Item>
    <Item ItemID="C">Straw</Item>
    <Item ItemID="D">Napkin</Item>
  </Order>
</xml>

如果您选择了@xml单独来看,你会看到它包含根节点dummyTag。我们不需要它,所以我们使用以下方法删除它指示 https://msdn.microsoft.com/en-us/library/ms189068.aspx#Anchor_1 xmltext in FOR XML EXPLICIT query:

,@xml AS [xml!1!!xmltext]

虽然MSDN中的解释听起来比较复杂,但实际上它告诉解析器选择contents of XML根节点。

不确定查询有多快,但目前我正在放松,像绅士一样喝着苏格兰威士忌,同时平静地看着代码......

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

使用 FOR XML PATH 时如何删除嵌套查询中的冗余命名空间 的相关文章

随机推荐