I have an xml structure in an existing SQL Server 2005 database table with a particular namespace defined, I need to query out the XML and in the process, change the namespace prefix to become the default namespace. The old xml has the namespace defined on the root node and child nodes and I know how to replace the root easily enough, but not the child node's namespace.
Current Data:
<sg:Settings xmlns:sg="uri:mynamespace">
<sg:SomeData xmlns:sg="uri:mynamespace"/>
</sg:Settings>
Using the SQL:
WITH XMLNAMESPACES
('uri:mynamespace' as sg)
SELECT
settingsNode.query('<Settings xmlns="uri:mynamespace"> { sg:SomeData } </Settings> ')
FROM
SettingsTable CROSS APPLY
SettingsXml.nodes('/sg:Settings') T(settingsNode)
I can get the following:
<Settings xmlns="uri:mynamespace">
<sg:SomeData xmlns:sg="uri:mynamespace"/>
</Settings>
But I'm trying to get this:
<Settings xmlns="uri:mynamespace">
<SomeData/>
</Settings>
Is there a way to merge namespaces using SQL XQuery?
If you would like to replace it with space
update tbl_Archive set XML.modify('delete /*:Document/*:Volume[text()]/#xmlns:sg')
Related
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
My XML has multiple default name spaces, my below
<BusMsg>
<AppHdr xmlns="urn:iso:std:iso:20022:tech:xsd:head.001.001.01" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="urn:iso:std:iso:20022:tech:xsd:head.001.001.01 General_head_001_001_01_20160503.xsd">
<CreDt>2017-06-29T05:32:11.147Z</CreDt>
<Prty>abc</Prty>
</AppHdr>
<Document xmlns="urn:iso:std:iso:20022:tech:xsd:pacs.008.001.05" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="urn:iso:std:iso:20022:tech:xsd:pacs.008.001.05 SCT_pacs_008_001_05_20160503.xsd">
<FIToFICstmrCdtTrf>
<GrpHdr>
<MsgId>NATAAU33XXX2017062918789018AK12503</MsgId>
<CreDtTm>2017-06-29T05:32:11.147Z</CreDtTm>
<NbOfTxs>1</NbOfTxs>
<SttlmInf>
<SttlmMtd>abc</SttlmMtd>
<ClrSys>
<Cd>abc</Cd>
</ClrSys>
</SttlmInf>
<InstgAgt>
<FinInstnId>
<BICFI>abcdd</BICFI>
</FinInstnId>
</InstgAgt>
<InstdAgt>
<FinInstnId>
<BICFI>abcde</BICFI>
</FinInstnId>
</InstdAgt>
</GrpHdr>
</FIToFICstmrCdtTrf>
</Document>
</BusMsg>
I tried like below, but didnt work, its giving me null as output
SELECT f.PURPOSE
FROM tem_table,
XMLTABLE( xmlnamespaces(default 'urn:iso:std:iso:20022:tech:xsd:head.001.001.01 urn:iso:std:iso:20022:tech:xsd:pacs.008.001.05'), '/BusMsg/Document'
PASSING XMLTYPE(tem_table.SOURCE_MESSAGE_TEXT)
COLUMNS PURPOSE VARCHAR2(30) PATH 'FIToFICstmrCdtTrf/GrpHdr/MsgId') f
WHERE id = '5bf8356b2e63';
Any one idea having on how to handle this
Just because your XML document has different default namespaces in various elements, doesn't mean you have to use default namespaces to put them apart.
The namespace mappings you declare in the XMLTABLE function are only relevant int he XQuery expressions of this XMLTABLE call.
If you want to match the namespace urn:iso:std:iso:20022:tech:xsd:head.001.001.01 you have two options
declare it as default namespace and don't prefix the elements/attributes in the XQuery expressions.
assign it to a namespace prefix and also use that prefix in the XQuery expressions.
XMLTABLE(xmlnamespaces(default 'urn:iso:std:iso:20022:tech:xsd:head.001.001.01'
, 'urn:iso:std:iso:20022:tech:xsd:pacs.008.001.05' AS "n")
, '/BusMsg/Document'
PASSING XMLTYPE(tem_table.SOURCE_MESSAGE_TEXT)
COLUMNS PURPOSE VARCHAR2(30) PATH 'n:FIToFICstmrCdtTrf/n:GrpHdr/n:MsgId'
) f
I've assigned the NS ending in ".01" as default namespace and did not prefix the elements in the main QPath expression. I've also assigned the alias "n" to the other namespace, and also prefixed the elements from that namespace in the COLUMNS XQuery expression.
I might have done some typos and it might be better reversed to have less namespace prefixes.
I want to generate the following xml doc in db2 and it has several namespaces:
<?xml version="1.0" encoding="UTF-8"?>
<ecore:EPackage xmi:version="2.0" xmlns:xmi="http://www.omg.org/XMI"
xmlns:ComIbmCompute.msgnode="ComIbmCompute.msgnode"
xmlns:ComIbmDatabase.msgnode="ComIbmDatabase.msgnode"
xmlns:ComIbmWSInput.msgnode="ComIbmWSInput.msgnode"
xmlns:ComIbmWSReply.msgnode="ComIbmWSReply.msgnode"
xmlns:ecore="http://www.eclipse.org/emf/2002/Ecore"
xmlns:eflow="http://www.ibm.com/wbi/2005/eflow"
xmlns:utility="http://www.ibm.com/wbi/2005/eflow_utility"
nsURI="myflow/FIPRRCV.msgflow" nsPrefix="myflow_FIPRRCV.msgflow">
This does not work:
`SELECT XMLELEMENT(NAME "ecore:EPackage",
XMLNAMESPACES('eclipse.org/emf/2002/Ecore'; AS "ecore")) as "result"
FROM SYSIBM.SYSDUMMY1 WITH UR;`
How can I define multiple namespaces and use them in elements and attributes?
The function to use is called XMLNAMESPACES. The name suggests it is not a single, but multiple namespaceS are possible. :)
You can provide several namespace declarations in a comma-separated list. Only one namespace can be set as default namespace. Try something like this:
SELECT XMLELEMENT(NAME "ecore:EPackage",
XMLNAMESPACES('eclipse.org/emf/2002/Ecore' AS "ecore",
'example.com/foobar' as "foobar")) as "result"
FROM SYSIBM.SYSDUMMY1
If you need to add attributes with a prefix in their name, then just pass that combined string as attribute name to XMLATTRIBUTES. The xmi:version="2.0" in your example is "xmi:version" as name with a value of 2.0.
I need to create a SQL Server script and a part of the script is selecting the names of the immediate child nodes of the root node and convert it to a (n)varchar. I don't need the attributes or content of the node.
This is an example of the xml:
declare #XML xml
set #XML =
'
<config>
<module1 />
<module2 />
</config>
'
I want the result like this:
module1
module2
Note that the xml is not hardcoded and can have many different child nodes.
I've already taken a look at this (msdn)link but at first sight it doesn't seem possible with those XML methods.
Many thanks,
Kjell
If you want the XML of the child nodes you mentioned you can use the Query method, for example;
select
cast(#XML.query('//GuiConfiguration/Activities') as nvarchar(max)),
cast(#XML.query('//GuiConfiguration/Reservations') as nvarchar(max))
EDIT: Answer to refined question
To get the names of the immediate child nodes of the root you can use this;
select
cast(t.c.query('local-name(.)') as nvarchar(max))
from
#xml.nodes('//*[1]/child::node()') as t(c)
Hi I have the following SQL to try and parse xml and extract the "OrderNumber". The problem i have is this xml (which i have no control over) has a wierd xml namespace. I changed it to abc.com just for this example, but its something else. Anyway, when that namepace is present, the T-SQL returns a null in the result. So it doesn't play nicely with the namespace. If I remove the namespace manually or doing a search and replace via T-SQL, it works just fine. I guess i can just do a search and replace but that solution just bothers me. Was wondering if anyone else nows a better way around this? And maybe an explanation of why it doesn't like namespaces? Would really appreciate some advice. Thanks!
Declare #Transmission xml
set #Transmission = '<Transmission>
<Requests>
<SubmitOrdersRequest>
<Orders>
<Order xmlns="http://www.abc.com">
<OrderNumber>123</OrderNumber>
</Order>
</Orders>
</SubmitOrdersRequest>
</Requests>
</Transmission>'
select #Transmission.value('(Transmission/Requests/SubmitOrdersRequest/Orders/Order/OrderNumber/text())[1]', 'varchar(100)')
Children nodes inherit the namespace of the parent, unless given a namespace themselves. you have to define namespaces using WITH XMLNAMESPACES, and properly qualify node names using them.
Declare #Transmission xml
set #Transmission = '<Transmission>
<Requests>
<SubmitOrdersRequest>
<Orders>
<Order xmlns="http://www.abc.com">
<OrderNumber>123</OrderNumber>
</Order>
</Orders>
</SubmitOrdersRequest>
</Requests>
</Transmission>';
with xmlnamespaces('http://www.abc.com' as ns1)
select #Transmission.value('(Transmission/Requests/SubmitOrdersRequest/Orders/ns1:Order/ns1:OrderNumber/text())[1]', 'varchar(100)')
Note: The reason for namespaces is that names are contextual things. Order can mean in your case a purchase but in another context it could mean display rack order. The namespace gives the name more uniqueness.