Error: XML declaration must be the first node in the document, and no white space characters are allowed to appear before it - sql

The functionality is like, we could write the plane SQL queries in XML and then we could import that xml in Product to see the changes in database.
In Update statement, I need to use the below update query. But getting 'XML declaration must be the first node in the document' error when trying to set column value.
<?xml version="1.0" encoding="utf-8"?>
<Metadata ClientSchemaVersion="1.1" Name="DummyName">
<Differences>
<Updates>
---
---
Begin
Update TABLE_NAME
Set //In next line, error is comming
ColumnName='<?xml version=''1.0'' encoding=''utf-16le'' ?><scenario xmlns='Text'><id>12345</id><title>
--
--
--
WHERE Condition
END
</Differences>
</Metadata>
How I could achieve that use case. Could someone help me out here.
Note- The same Update Query is working fine if ran in SQL Server directly

Two XML declarations (<?xml ... ?>) are not allowed in an XML document. Only one is permitted, and it must be at the very top of the document.
Here are two ways you can repair your XML:
Remove the second XML declaration. The default for that SQL-embedded XML will then be XML version 1.0 with UTF-8 encoding.
If the processing application supports it, wrap the SQL in a CDATA section such that the SQL-embedded XML document is no longer parsed as XML.
<![CDATA[
... SQL with embedded XML that can contain its own XML declaration ...
]]>
See also
Error: The processing instruction target matching "[xX][mM][lL]" is not allowed

Related

Exception cx_st_match_element when deserializing XML?

I'm having trouble getting a simple transformation for XML to work in ABAP. I keep getting the exception cx_st_match_element when I try to execute it on a test XML document inside of a report.
I have the following XML that I want to transform into an ABAP internal table:
<?xml version="1.0" encoding="UTF-8"?>
<studenten xmlns="http://www.foo.be/bar/preinschrijvingsflow"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.foo.be/bar/preinschrijvingsflow bar_studenten.xsd">
<student>
<barGuid>1</barGuid>
<familienaam>Doe</familienaam>
<voornaam>John</voornaam>
<geslacht>1</geslacht>
<nationaliteit>BE</nationaliteit>
<geboortedatum>1995-11-18</geboortedatum>
<geboorteplaats>Antwerpen</geboorteplaats>
<email>John.Doe#gmail.com</email>
<straatNummer>Grote Markt 1 bus 0102</straatNummer>
<postcode>1000</postcode>
<gemeente>Brussel</gemeente>
<land>BE</land>
<telefoonnummer>+32123456789</telefoonnummer>
<academiejaar>2021</academiejaar>
</student>
</studenten>
To this end I defined the following simple transformation I called zc_tr_student:
<?sap.transform simple?>
<tt:transform
xmlns="http://www.foo.be/bar/preinschrijvingsflow"
xmlns:tt="http://www.sap.com/transformation-templates"
xmlns:ddic=" http://www.sap.com/abapxml/types/dictionary">
<tt:root name="studenten" type="ddic:ZCTT_bar_STUDENT"/>
<tt:template>
<studenten>
<tt:loop ref=".studenten" name="studenten">
<student>
<barGuid tt:value-ref="$studenten.bar_guid"/>
<familienaam tt:value-ref="$studenten.familienaam"/>
<voornaam tt:value-ref="$studenten.voornaam"/>
<geslacht tt:value-ref="$studenten.geslacht"/>
<nationaliteit tt:value-ref="$studenten.nationaliteit"/>
<geboortedatum tt:value-ref="$studenten.geboortedatum"/>
<geboorteplaats tt:value-ref="$studenten.geboorteplaats"/>
<email tt:value-ref="$studenten.email"/>
<straat_nummer tt:value-ref="$studenten.straat_nummer"/>
<postcode tt:value-ref="$studenten.postcode"/>
<gemeente tt:value-ref="$studenten.gemeente"/>
<land tt:value-ref="$studenten.land"/>
<telefoonnummer tt:value-ref="$studenten.telefoonnummer"/>
<academiejaar tt:value-ref="$studenten.academiejaar"/>
</student>
</tt:loop>
</studenten>
</tt:template>
</tt:transform>
In the tt:value-refattributes I refer to the field in the DDIC line type of the ABAP internal table corresponding to the tag in the XML.
If I call this simple transformation from an ABAP report like this:
call transformation zc_tr_student
source xml lv_bxml
result studenten = p_student.
The cx_st_match_element is thrown.
I validated both the syntax of the file and its adherence to the schema. The XML file and the XSD file are present in the same directory on the application server. I have no idea why the ST fails as the cx_st_match_element instance does not have any useful information except that it expected a studenten element. That element is clearly present in the XML file as the root element.
I'm inexperienced with defining simple transformations and I can't spot my error myself. Thank you in advance for your help,
Joshua

SQL SERVER xml with CDATA

I have a table in my database with a column containing xml. The column type is nvarchar(max). The xml is formed in this way
<root>
<child>....</child>
.
.
<special>
<event><![CDATA[text->text]]></event>
<event><![CDATA[text->text]]></event>
...
</special>
</root>
I have not created the db, I cannot change the way information is stored in it but I can retrieve it with a select. For the extraction I use
select cast(replace(xml,'utf-8','utf-16')as xml)
from table
It works well except for cdata, whose content in the query output is: text -> text
Is there a way to retrieve also the CDATA tags?
Well, this is - as far as I know - not possible on normal ways...
The CDATA section has one sole reason: include invalid characters within XML for lazy people...
CDATA is not seen as needed at all and therefore is not really supported by normal XML methods. Or in other words: It is supported in the way, that the content is properly escaped. There is no difference between correctly escaped content and not-escaped content within CDATA actually! (Okay, there are some minor differences like including ]]> within a CDATA-section and some more tiny specialties...)
The big question is: Why?
What are you trying to do with this afterwards?
Try this. the included text is given as is:
DECLARE #xml XML =
'<root>
<special>
<event><![CDATA[text->text]]></event>
<event><![CDATA[text->text]]></event>
</special>
</root>'
SELECT t.c.query('text()')
FROM #xml.nodes('/root/special/event') t(c);
So: Please explain some more details: What do you really want?
If your really need nothing more than the wrapping CDATA you might use this:
SELECT '<![CDATA[' + t.c.value('.','varchar(max)') + ']]>'
FROM #xml.nodes('/root/special/event') t(c);
Update: Same with outdated FROM OPENXML
I just tried how the outdated approach with FROM OPENXML handles this and found, that there is absolutely no indication in the resultset, that the given text was within a CDATA section originally. The "Some value here" is exactly returned in the same way as the text within CDATA:
DECLARE #doc XML =
'<root>
<child>Some value here </child>
<special>
<event><![CDATA[text->text]]></event>
<event><![CDATA[text->text]]></event>
</special>
</root>';
DECLARE #hnd INT;
EXEC sp_xml_preparedocument #hnd OUTPUT, #doc;
SELECT * FROM OPENXML (#hnd, '/root',0);
EXEC sp_xml_removedocument #hnd;
This is how to include cdata on child nodes in XML, using pure SQL. But; it's not ideal.
SELECT 1 AS tag,
null AS parent,
'10001' AS 'Customer!1!Customer_ID!Element',
'AirBallon Captain' AS 'Customer!1!Title!cdata',
'Customer!1' = (
SELECT
2 AS tag,
NULL AS parent,
'Wrapped in cdata, using explicit' AS 'Location!2!Title!cdata'
FOR XML EXPLICIT)
FOR XML EXPLICIT, ROOT('Customers')
CDATA is included, but Child element is encoded using
>
instead of >
Which is so weird from a sensable point of view. I'm sure there are technical explanations, but they are stupid, because there is no difference in the FOR XML specification.
You could include the option type on the inner child node and then loose cdata too..
BUT WHY OH WHY?!?!?!?! would you (Microsoft) remove cdata, when I just added it?
<Customers>
<Customer>
<Customer_ID>10001</Customer_ID>
<Title><![CDATA[AirBallon Captain]]></Title>
<Location>
<Title><![CDATA[wrapped in cdata, using explicit]]></Title>
</Location>
</Customer>
</Customers>

XML parsing error in SQL Server stored procedure

I want to parse the below XML in a SQL Server stored procedure and update some tables based on this XML. I have implemented the same using OPENXML but now there is one more line added to the beginning of the XML, because of which am getting unexpected errors. Is it possible to somehow skip the first tag alone while parsing
Parsing code :
set #Lead= (select lead
from openxml(#DOCHANDLE,'/DBO.TBLLEADS',2) with (lead INT 'LEAD'))`
XML here:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<LEADS>
<LEAD>6680299</LEAD>
<JOBNO>50919</JOBNO>
<BEGINDATE>4-04-2013</BEGINDATE>
<ENDDATE>04/14/2013</ENDDATE>
</LEADS>
Well, not the most elegant solution, but will get it back to working:
Before you prepare your XML document, run this statement on the variable containing the XML:
SET #XMLVariable = REPLACE(#XMLVariable, '<?xml version="1.0" encoding="UTF-8" standalone="yes"?>', '')
Basically you're leveraging the REPLACE function to replace the unnecessary header string with nothing.

XML Import with "alternate" form or xml formatting

I have successfully imported an XML file parsing elements info table attributes using this xml data formating:
<PN>
<guid>aaaa</guid>
<dataInput>0</dataInput>
<deleted>false</deleted>
<customField1></customField1>
<customField2></customField2>
<customField3></customField3>
<description></description>
<name>name1></name>
<ccid>CC007814</ccid>
<productIds>bbbb</productIds>
</PN>
but it errors whwen I input an XML in this format:
<PN guid="aaaa"
deleted="false"
customField1=""
customField2=""
customField3=""
description=""
modified="2010-10-20T00:00:00.001"
created="2010-05-20T18:07:10.416"
name="name1"
ccid="CC006035"
productIds="bbbb"/>
Is this later form usable? Any help would be appreciated. Thanks.
It's usable, but you're looking at the difference between using tags (your first example) and attributes (your second example). Your processing is slightly different.

Import Xml nodes as Xml column with SSIS

I'm trying to use the Xml Source to shred an XML source file however I do not want the entire document shredded into tables. Rather I want to import the xml Nodes into rows of Xml.
a simplified example would be to import the document below into a table called "people" with a column called "person" of type "xml". When looking at the XmlSource --- it seem that it suited to shredding the source xml, into multiple records --- not quite what I'm looking for.
Any suggestions?
<people>
<person>
<name>
<first>Fred</first>
<last>Flintstone</last>
</name>
<address>
<line1>123 Bedrock Way</line>
<city>Drumheller</city>
</address>
</person>
<person>
<!-- more of the same -->
</person>
</people>
I didn't think that SSIS 2005 supported the XML datatype at all. I suppose it "supports" it as DT_NTEXT.
In any case, you can't use the XML Source for this purpose. You would have to write your own. That's not actually as hard as it sounds. Base it on the examples in Books Online. The processing would consist of moving to the first child node, then calling XmlReader.ReadSubTree to return a new XmlReader over just the next <person/> element. Then use your favorite XML API to read the entire <person/>, convert the resulting XML to a string, and pass it along down the pipeline. Repeat for all <person/> nodes.
Could you perhaps change your xml output so that the content of person is seen as a string? Use escape chars for the <>.
You could use a script task to parse it as well, I'd imagine.