How do I remove redundant namespace in nested query when using FOR XML PATH

前端 未结 6 1945
长情又很酷
长情又很酷 2020-11-28 12:54

UPDATE: I\'ve discovered there is a Microsoft Connect item raised for this issue here

When using FOR XML PATH

6条回答
  •  天涯浪人
    2020-11-28 13:20

    The problem here is compounded by the fact that you cannot directly declare the namespaces manually when using XML PATH. SQL Server will disallow any attribute names beginning with 'xmlns' and any tag names with colons in them.

    Rather than having to resort to using the relatively unfriendly XML EXPLICIT, I got around the problem by first generating XML with 'cloaked' namespace definitions and references, then doing string replaces as follows ...

    DECLARE @Order TABLE (
      OrderID INT, 
      OrderDate DATETIME)
    
    DECLARE @OrderDetail TABLE (
      OrderID INT, 
      ItemID VARCHAR(1), 
      ItemName 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)
    
    declare @xml xml
    
    set @xml = (SELECT
      'http://test.com/order' as "@xxmlns..od",  -- 'Cloaked' namespace def
      (SELECT OrderID AS "@OrderID", 
        (SELECT 
          ItemID AS "@od..ItemID", 
          ItemName AS "data()" 
         FROM @OrderDetail 
         WHERE OrderID = o.OrderID 
         FOR XML PATH ('od..Item'), TYPE)
       FROM @Order o
       FOR XML PATH ('od..Order'), TYPE)
      FOR XML PATH('xml'))
    
    set @xml = cast(replace(replace(cast(@xml as nvarchar(max)), 'xxmlns', 'xmlns'),'..',':') as xml)
    
    select @xml
    

    A few things to point out:

    1. I'm using 'xxmlns' as my cloaked version of 'xmlns' and '..' to stand in for ':'. This might not work for you if you're likely to have '..' as part of text values - you can substitute this with something else as long as you pick something that makes a valid XML identifier.

    2. Since we want the xmlns definition at the top level, we cannot use the 'ROOT' option to XML PATH - instead I needed to add an another outer level to the subselect structure to achieve this.

提交回复
热议问题