How to generate namespaces in XML docs with Db2? - sql

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.

Related

How to use XMLTABLE with multiple default namespaces

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.

Mybatis: How can I get the first element from the passed parameter?

Given that my parameterType is an ArrayList, is it possible to get the first element from that list and use it in the where clause ?
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="db">
<select id="selectFlag" resultType="java.lang.Boolean" parameterType="java.util.ArrayList">
select TOP 1 'true' from customers where id = ???
</select>
</mapper>
If your query uses one id, why are you sending a list and then picking the first one for the query?
Change your parameterType to an int (or whatever type the id has), don't send a list. This is a simple approach that also conveys the information that you are only retrieving data based on a single id. Your condition then changes to something like:
where id = #{id}
If you must absolutely send an ArrayList (for whatever reason) then MyBatis supports OGNL expressions so something like this should work:
where id = #{list[0]}
Unfortunately MyBatis lacks on the documentation side, so you can find out about things like this only by looking at the source code.

Xml node name Parsing using SQL

I need to get the value of the tag "supervisor....." The problem is that those tag name are dynamic, they change for each person. I have tried using Extract value but it works only if you use a static tag name.
It is in Oracle environment.
Thanks for your help.
Ourson
XML Extract
<?xml version="1.0" encoding="UTF-8"?>
<TRANSACTION>
<TransCtx>
<supervisorCalcAttributes classType="Ht">
<SupervisorId10977 classType="s">Matt, Clinton</SupervisorId10977>
<SupervisorId4753 classType="s">Bob, Sponge</SupervisorId4753>
<FND_ENTERPRISE_ID classType="s">1</FND_ENTERPRISE_ID>
</supervisorCalcAttributes>
</TransCtx>
</TRANSACTION>
SQL Query
select
Extractvalue( xmltype('<root>'||txndata.data_cache||'</root>'),
'root/TRANSACTION[1]/TransCtx[1]/supervisorCalcAttributes[1]/**LineItem**[1]' ) as test
from hrc_txn_data txndata, hrc_txn_header txnhe
where txnhe.transaction_id=txndata.transaction_id

Parsing SQL with bad xml namespace

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.

Replacing xml namespace prefixes in SQL Server with XQuery

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')