How to avoid in SQL to store an XML <option></option> like <option />? - sql-server

When I try to store a XML in SQL than have an empty Element, SQL just change it and store it with only one tag for the element.
For Example the XML to store is:
<ROOT>
<FIRSTNAME>ROGER</FIRSTNAME>
<MIDDLENAME></MIDDLENAME>
</ROOT>
Then Sql stored it like
<ROOT>
<FIRSTNAME>ROGER</FIRSTNAME>
<MIDDLENAME />
</ROOT>
The sql update is just very simple:
UPDATE
SESIONESREPORTES
SET
SER_PARAMETROS = '
<ROOT>
<FIRSTNAME>ROGER</FIRSTNAME>
<MIDDLENAME></MIDDLENAME>
</ROOT>'
WHERE SER_ID=7
I need like this because I have some query that fails when a element is empty, you can see it here..
Merging many rows in a single

I don't think you can, looking at the following link:
XML Data Type and Columns
According to this (XML Storage Options Section):
The data is stored in an internal representation that preserves the
XML content of the data. This internal representation includes
information about the containment hierarchy, document order, and
element and attribute values. Specifically, the InfoSet content of the
XML data is preserved. For more information about InfoSet, visit
http://www.w3.org/TR/xml-infoset. The InfoSet content may not be an
identical copy of the text XML, because the following information is
not retained: insignificant white spaces, order of attributes,
namespace prefixes, and XML declaration.
So the internal storage will strip out all parts it deems unnecessary, the document goes on to state that if you need an exact copy of the XML document and not just the content, you should use either [n]varchar(max) or varbinary(max)

<MIDDLENAME></MIDDLENAME>
and
<MIDDLENAME/>
are equivalent; any XML parser will treat them identically - as an empty element. If your query fails on an empty element, it will fail on either of them. You'll need to either rewrite your query to handle empty elements, put some content in the <MIDDLENAME> element, or omit the element entirely (if your query can handle it's absence.)

Related

Include text in ForXMLPath query in SQL Server

I want to include a line (simple text) in ForXMLPath query as
<Cat>
but I am having difficulties.
When I try it brings in weird characters with it.
Please help.
Thanks.
select
'<Cat>'
I expect this
<Cat>
but it displays below
<Cat>
I must admit, that your question is not clear...
XML is not just some text with fancy extras, but a very strictly organised text based container for data.
A simple SELECT '<Cat>' would never return as <Cat> without a FOR XML somewhere in your query. So please show us a (reduced!) example of your full query and the expected output, best provided as MCVE (a stand-alone sample with DDL, sample data, own attempt and expected output).
Just some general remarks:
If you want to place <Cat> within your XML the whole output will be broken XML. This opening tag demands for a closing </Cat> (or - alternatively - a self-closing <Cat />)
Assumably you try to add out-written tags to your XML as you'd do it in XSLT, JS, ASP.Net or any other XML/HTML producing approach.
Assumably your solution will be a FOR XML PATH() approach without the need of an out-written tag within your XML.
Just to give you an idea:
SELECT 'test' AS [SomeElement] FOR XML PATH('SomeRowTag'),ROOT('SomeRootTag');
prouces this XML
<SomeRootTag>
<SomeRowTag>
<SomeElement>test</SomeElement>
</SomeRowTag>
</SomeRootTag>
If you want to add a <Cat> element you could use an XPath like here
SELECT 'test' AS [Cat/SomeElement] --<-- You can add nest-levels here!
FOR XML PATH('SomeRowTag'),ROOT('SomeRootTag');
The result
<SomeRootTag>
<SomeRowTag>
<Cat>
<SomeElement>test</SomeElement>
</Cat>
</SomeRowTag>
</SomeRootTag>

Are the elements of an XML alwas ordered if I get them from SQL Server 2012

I found
"Order of Attributes" The order of attributes in an XML instance is not preserved. When you query the XML instance stored in the xml type column, the order of attributes in the resulting XML may be different from the original XML instance."
from a link https://msdn.microsoft.com/en-us/library/bb510442.aspx
Q1) does that mean elements like following will not have any order that means
I may get xyz1 then xyz. Or it will be ordered?
xyz
xyz1
XML elements are ordered; XML attributes are not. So, for this XML,
<root>
<element1 attribute1="value1" attribute2="value2">element1 value</element>
<element2 attribute3="value3" attribute4="value4">element2 value</element>
</root>
the elements, element1 and element2 have significant ordering, and attributes attribute1 through attribute4 have insignificant ordering.
See also XML attribute vs XML element.
As stated in https://www.w3.org/TR/xml-infoset/#infoitem.document order of elements is part of XML infoset. All libraries should preserve order. Notice that:
[children] An ordered list of child information items, in document
order.
and
[attributes] An unordered set of attribute information items ...
Ordered list <> unordered set.

XPath query: parsing multiple paths using the same query (Cross Apply / .nodes() )

I have a rather big and structured XML receipt which one I want to parse into a relational database. There are some equal structures on different levels, so it'd be very good to parse them using the same SQL statement. Like:
DECLARE #XMLPath varchar(127)
SET #XMLPath = 'atag/btag/item'
INSERT INTO XMLReadItems
SELECT ci.InvoiceID,
T.c.value('productname[1]', 'varchar(63)') AS InvoiceTarget,
T.c.value('unit[1]', 'varchar(15)') AS Unit,
FROM #XMLItems ci CROSS APPLY XMLCol.nodes(*[local-name()=sql:variable("#XMLPath")]') T(c)
Where #XMLPath could be a string from a variable or even a field from a table (what about using sql:column()?). But any of them I couldn't make work.
I can only use a static string in XMLCol.nodes().
There is no way you can construct XQuery parameter dynamically as it is limited to literal string only. See what MSDN says about the parameter of nodes() XML method :
XQuery
Is a string literal, an XQuery expression. If the query expression constructs nodes, these constructed nodes are exposed in the resulting rowset. If the query expression results in an empty sequence, the rowset will be empty. If the query expression statically results in a sequence that contains atomic values instead of nodes, a static error is raised.
Forcing to pass SQL variable to nodes() method would trigger error :
The argument 1 of the XML data type method "nodes" must be a string literal.
The trick you're trying to implement only works for matching element by name dynamically, not constructing the entire XPath dynamically. For example, the following should work fine to shred on item elements :
SET #elementName = 'item'
SELECT .....
FROM #XMLItems ci
CROSS APPLY XMLCol.nodes('//*[local-name()=sql:variable("#elementName")]') T(c)
In the end there is no workaround to this limitation as far as I can see, unless you want to go farther to construct the entire query dynamically (see: sp_executesql).

SQL Server XML Value formatting newline

T-SQL XML value loses new line formats
I have XML file loaded into SQL server. I query this file to extract the nodes with value.
The problem is the new line characters are lost while selection. How to retain formatting so that when I display the text on the web, it not appear messy without line breaks.
See text and screenshots for details
T-SQL code:
declare #Text xml ;
set #Text= '<?xml version="1.0" encoding="utf-8"?>
<topic>
<L1>
<Subject>Subject text</Subject>
<Details>
Story Details are
This is paragraph
Text after After two line breaks
Text after After two line breaks
</Details>
</L1>
</topic>'
;with t as (select #Text [xmlcolumn])
--select * from t
SELECT x.a.value('(Subject)[1]','nvarchar(max)') as [Subject]
, x.a.value('(Details)[1]','nvarchar(max)') as [Details]
FROM t
cross apply
t.xmlcolumn.nodes('//L1') x(a)
Update: I misread your question - the problem with the newlines is purely in SQL Server Management Studio - it cannot represent those newlines. When you read your XML from an application in C# or VB.NET, those newlines will still be there - trust me.
But this original answer might also be relevant in other cases - you need to be aware that SQL Server is not storing your XML "as is" - it parses and converts it. So when you ask to get it back, it might look slightly different, but it's still the same XML functionally.
Yes, this is normal, expected behavior.
SQL Server stores your XML in a tokenized format - e.g. it doesn't store the actual, textual representation of your XML, but it parses and tokenizes your XML into XML fragments that are then stores inside this XML datatype.
Therefore, when you query it again, you'll get back a semantically correct and identical representation - but there's a possibility that certain textual representations are different.
E.g. when you pass in an empty XML element something like this:
<MyEmptyElement></MyEmptyElement>
you'll get back the "short" form of that when you retrieve the XML from SQL Server again:
<MyEmptyElement />
This is not the exact same text - but it's 100% the same XML from a semantic perspective.
As far as I know, you cannot influence this behavior in any way - you'll just have to live with it.

Decoding the xml to html content from t sql xml column

Earlier,In TSQL we have an XML column to store the html data with xml serialization.
But now we think to keep the html content in CDATA region.
How can I convert the existing xml serialized content to the corresponding html content?
e.g. XML serialized column data : <Node Txt="<b>bold text</b>" />
Expected corresponding transform : <Node><![CDATA[<b>bold text</b>]]></Node>
The above transformation is expected to be carried over by sql script.
I think of a solution to replace all those 5 xml special chars corresponding replacement characters (&,<,>,",etc.). But I dont think string manipulation may work in xml to html transformation.
Any cleaner way or idea to transform those existing xml to html data?
Maybe use the PHP function htmlspecialchars to translate it. If it's a one time thing, this shouldn't be too much trouble for you.
If not, you could code something up using SQL string functions. http://msdn.microsoft.com/en-us/library/ms186862.aspx

Resources