Reputation: 1277
I am using the SQL Query to return the result as XML using in SQL server. I am using the below SQL Query-
SELECT '1' AS [Column1]
UNION
SELECT '2' AS [Column2]
UNION
SELECT '' AS [Column3]
FOR XML PATH('Test'), ROOT('Rows')
Result XML:
<Rows>
<Test>
<Column1></Column1>
</Test>
<Test>
<Column1>1</Column1>
</Test>
<Test>
<Column1>2</Column1>
</Test>
</Rows>
Output would be like :
<Rows>
<Test>
<Column1/>
</Test>
<Test>
<Column1>1</Column1>
</Test>
<Test>
<Column1>2</Column1>
</Test>
</Rows>
Any help would be appreciate. Thanks in Advance.
Upvotes: 1
Views: 8455
Reputation: 2014
First, as mentioned by @marc-s in the comments, both representations are semantically equivalent according to the XML spec.
The representation of an empty element is either a start-tag immediately followed by an end-tag, or an empty-element tag.
http://www.w3.org/TR/REC-xml/#NT-content
See also:
https://stackoverflow.com/a/2279530/2266979
In the comments, you clarified that the self-closing tag representation involves fewer characters.
That only matters when consuming the XML outside of SQL Server, since in the server it "is stored internally in a binary format" (https://technet.microsoft.com/en-US/library/ms345115(v=SQL.90).aspx).
If you are consuming the XML outside of SQL Server, where these characters would matter, you have probably converted it to text. However, when you do that, SQL Server (2008, anyway) automatically uses self-closing tags.
For example:
SELECT CONVERT(varchar(max),CONVERT(xml,'<tag></tag>'));
Will return:
<tag/>
So all you should need to do is convert your final result to text.
This assumes that you have typed XML. If you create your XML with FOR XML PATH
without specifying the TYPE
keyword, you are essentially just producing text which looks like XML.
So this:
SELECT CONVERT(varchar(max),(SELECT '' AS 'tag' FOR XML PATH('')));
Will return:
<tag></tag>
If you instead use the TYPE
keyword:
SELECT CONVERT(varchar(max),(SELECT '' AS 'tag' FOR XML PATH(''), TYPE));
You will get:
<tag/>
Upvotes: 1
Reputation: 1277
Actually If we inner the XML then it will return the Tag as self closing. Please see the below SQL code:
DECLARE @TempData Table
(
Column1 NVARCHAR(250)
)
INSERT INTO @TempData values('Column1')
INSERT INTO @TempData values('Column2')
INSERT INTO @TempData values('')
SELECT
(
SELECT * FROM @TempData FOR XML PATH('Test'), Type
)
For XML PATH (''),
ROOT('Rows')
Output:
<Rows>
<Test>
<Column1>Column1</Column1>
</Test>
<Test>
<Column1>Column2</Column1>
</Test>
<Test>
<Column1 />
</Test>
</Rows>
Upvotes: 4
Reputation: 47945
I think the result is correct you are selecting an empty string try selecting null:
SELECT '1' AS [Column1]
UNION
SELECT '2' AS [Column2]
UNION
SELECT NULL AS [Column3]
FOR XML PATH('Test'), ROOT('Rows')
Result:
<Rows>
<Test />
<Test>
<Column1>1</Column1>
</Test>
<Test>
<Column1>2</Column1>
</Test>
</Rows>
That is even much less as you want.
Because you don't like to remove also the tag try this here:
declare @output nvarchar(max)
declare @XML xml = '
<Rows>
<Test>
<Column1></Column1>
</Test>
<Test>
<Column1>1</Column1>
</Test>
<Test>
<Column1>2</Column1>
</Test>
</Rows>'
set @output = replace(cast(@XML as nvarchar(max)), '<Column1></Column1>', '<Column1/>')
select @output
Sorry for hard encoding your xml result I cannot figger out right now how to set the output into @XML dynamically.
Upvotes: 1