MS SQL Server has data type of XML
since SQL Server 2005. The XML
data type is a subset of NVARCHAR
or VARCHAR
, so string data can be easily converted to XML value by running the following query/function.
DECLARE @data AS NVARCHAR(MAX)
SET @data = '<product>
<id>1</id>
<name>My Product</name>
<description>My Description</description>
<price>19.99</price>
</product>'
DECLARE @xml AS XML
SET @xml = CAST(@data AS XML)
SELECT @data, @xml
`</pre>
However, if the `<description>` element contains HTML value like, `<strong>My</strong> Description`, those HTML tags are encoded. As a result, the return value will be:
<pre>`<product>
<id>1</id>
<name>My Product</name>
<description>&lt;strong&gt;My&lt;/strong&gt; Description</description>
<price>19.99</price>
</product>
`</pre>
In order to avoid this situation, `<![CDATA[...]]>` should be used. How can we achieve it? Let's assume that there is a record on the `@products` table.
<pre>`DECLARE @products TABLE (
id INT,
name NVARCHAR(MAX),
description NVARCHAR(MAX),
price DECIMAL(18, 2)
)
INSERT INTO @products (
[id], [name], [description], [price]
) VALUES (
1, 'My Product', '<strong>My</strong> Description', 19.99
)
SELECT id, name, description, price FROM @products WHERE id = 1
`</pre>
It returns the record like:
<table>
<thead>
<tr>
<th>id</th>
<th>name</th>
<th>description</th>
<th>price</th>
</tr>
</thead>
<tbody>
<tr>
<td>1</td>
<td>My Product</td>
<td><strong>My</strong> Description</td>
<td>19.99</td>
</tr>
</tbody>
</table>
Now, let's convert this record to XML, especially with `CDATA` tag.
<pre>`DECLARE @result AS NVARCHAR(MAX)
SET @result = (
SELECT * FROM (
SELECT
1 AS Tag,
0 AS Parent,
[id] AS [product!1!id!Element],
[name] AS [product!1!name!Element],
NULL AS [description!2!!CDATA],
[price] AS [product!1!price!Element]
FROM
@products
WHERE [id] = 1
UNION ALL
SELECT
2 AS Tag,
1 AS Parent,
NULL,
NULL,
[description],
NULL
FROM
@products
WHERE [id] = 1
) AS q
FOR XML EXPLICIT
)
SELECT @result AS [String], CAST(@result AS XML) AS [XML]
`</pre>
And you will find the `String` field keeps `CDATA` value:
<pre>`<product><id>1</id><name>My Product</name><price>19.9900</price><description><![CDATA[<strong>My</strong> Description]]></description></product>
`</pre>
While, the `XML` field converts the value HTML encoded:
<pre>`<product>
<id>1</id>
<name>My Product</name>
<price>19.9900</price>
<description>&lt;strong&gt;My&lt;/strong&gt; Description</description>
</product>