Search code examples
sqlsql-serverxmlfor-xmlfor-xml-explicit

Remove xmlns="" name space declaration when using FOR XML EXPLICIT


I'm generating an XML document using FOR XML EXPLICIT:

declare @MyTable table (value xml);

insert into @MyTable values
 ('<foo bar="data1">content1</foo>')
,('<foo bar="data2">content2</foo>')
,('<foo bar="data3">content3</foo>');

select 1 as Tag, null as Parent
    , value as [x!1!!xml]
from @MyTable
for xml explicit;

And get such a response:

<x>
  <foo bar="data1" xmlns="">content1</foo>
</x>
<x>
  <foo bar="data2" xmlns="">content2</foo>
</x>
<x>
  <foo bar="data3" xmlns="">content3</foo>
</x>

The problem is that I don't need the xmlns attribute.

I found a solution, but it seems to be a kludge.

select 1 as Tag, null as Parent
    , cast (value as varchar(200)) as [x!1!!xml]
from @MyTable
for xml explicit;

Is there a more elegant way to solve the problem?

Do not offer using FOR XML PATH/RAW/AUTO.

EXPLICIT mode is must.


Solution

  • If the root element name (i.e. foo in the example data in the Question) is the same across all rows, then there is a simple method for accomplishing this:

    1. specify the AttributeName item (3rd item) in the column name. In terms of the example data, that would be foo.

    2. use the xmltext Directive (4th item) instead of xml.

    The column name would be:

    [x!1!foo!xmltext]
    

    And the full query would be:

    SELECT 1 AS [Tag], NULL AS [Parent]
        , value AS [x!1!foo!xmltext]
    FROM @MyTable
    FOR XML EXPLICIT;
    

    But if the root element name does vary, then the above method is not an option and it seems that the only way is to convert the XML data into NVARCHAR (a better choice than VARCHAR since XML and NVARCHAR are both UTF-16):

    SELECT 1 AS [Tag], NULL AS [Parent]
        , CONVERT(NVARCHAR(MAX), value) AS [x!1!!xml]
    FROM @MyTable
    FOR XML EXPLICIT;
    

    For more info, please see the MSDN page for Use EXPLICIT Mode with FOR XML.