PostgresSQL xpath with namespaces - sql

I would like to know how to use the xpath funtion in the following example:
The xml is inside a table called SR_DATA, field XMLDATA of type TEXT
The following is the structure of the xml document:
<?xml version="1.0" encoding="UTF-8"?>
<modulo modelCodeScheme="DocType" modelCodeSchemeVersion="01" modelCodeValue="TYPE_20a" modelCodeMeaning="SCREENING" group="groupname" type="format" xmlns="http://www.expr.com/2008/FMSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<AAAAA modelCodeScheme="MAM" modelCodeSchemeVersion="1" modelCodeValue="AN_MAM_6" modelCodeMeaning="Family1" tipodato="booleano">
<![CDATA[false]]>
</AAAAA>
<BBBBB modelCodeScheme="MAM" modelCodeSchemeVersion="1" modelCodeValue="AN_MAM_8" modelCodeMeaning="Family2" tipodato="booleano">
<![CDATA[false]]>
</BBBBB>
</modulo>
Let's say I want to read the text about the element named AAAAA, so my query looks like this:
SELECT (xpath('/modulo/AAAAA/text()', XMLDATA::xml) AS status
FROM SR_DATA;
My query doesn't raise any error but the resultset is empty; I suppose I have to map the NAMESPACES but I need a hint on how to do it.

You need to specify namespaces in the xpath function. The node contains multiple text nodes; you could combine the nodes together using array_to_string function:
SELECT TRIM(BOTH FROM array_to_string(xpath('/x:modulo/x:AAAAA/text()', XMLDATA::xml, ARRAY[
ARRAY['x', 'http://www.expr.com/2008/FMSchema']
]), ''))
FROM SR_DATA
-- false
Demo on db<>fiddle

Related

Trying to extract a namespace value from an xmltype

my BLOB (converted to XMLType) contains the following :
<?xml version="1.0" encoding="UTF-8"?><S2SCTScf:SCTScfBlkCredTrf xsi:schemaLocation="urn:S2SCTScf:xsd:$SCTScfBlkCredTrf SCTScfBlkCredTrf.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:S2SCTScf="urn:S2SCTScf:xsd:$SCTScfBlkCredTrf"><S2SCTScf:SndgInst>EBAPFRPA</S2SCTScf:SndgInst><S2SCTScf:RcvgInst>NWBKGB2X</S2SCTScf:RcvgInst><S2SCTScf:SrvcId>SCT</S2SCTScf:SrvcId><S2SCTScf:TstCode>P</S2SCTScf:TstCode><S2SCTScf:FType>SCF</S2SCTScf:FType><S2SCTScf:FileRef>NSCT220610000729</S2SCTScf:FileRef><S2SCTScf:RoutingInd>IND</S2SCTScf:RoutingInd><S2SCTScf:FileBusDt>2022-06-10</S2SCTScf:FileBusDt><S2SCTScf:FileCycleNo>11</S2SCTScf:FileCycleNo><S2SCTScf:FIToFICstmrCdtTrf xmlns="urn:iso:std:iso:20022:tech:xsd:pacs.008.001.02"><GrpHdr><MsgId>NSCT2206100007290000000000000000001</MsgId><CreDtTm>2022-06-10T09:52:54</CreDtTand
I wish to use SQL to extract the namespace value :
<S2SCTScf:FIToFICstmrCdtTrf xmlns="urn:iso:std:iso:20022:tech:xsd:pacs.008.001.02">
How would I do that - I tried XMLQuery but couldn't get it to work.
Many thanks
You can use FLOWR to delete the child elements and just return that single element:
SELECT XMLQUERY(
'declare namespace S2SCTScf="urn:S2SCTScf:xsd:$SCTScfBlkCredTrf";
copy $e := /S2SCTScf:SCTScfBlkCredTrf/S2SCTScf:FIToFICstmrCdtTrf
modify (
for $i in $e/*
return delete node $i
)
return $e'
PASSING value RETURNING CONTENT
).getStringVal() AS xmlns_element
FROM table_name
Which, for the sample data:
CREATE TABLE table_name (value) AS
SELECT XMLTYPE('<?xml version="1.0" encoding="UTF-8"?>
<S2SCTScf:SCTScfBlkCredTrf xsi:schemaLocation="urn:S2SCTScf:xsd:$SCTScfBlkCredTrf SCTScfBlkCredTrf.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:S2SCTScf="urn:S2SCTScf:xsd:$SCTScfBlkCredTrf">
<S2SCTScf:SndgInst>EBAPFRPA</S2SCTScf:SndgInst>
<S2SCTScf:RcvgInst>NWBKGB2X</S2SCTScf:RcvgInst>
<S2SCTScf:SrvcId>SCT</S2SCTScf:SrvcId>
<S2SCTScf:TstCode>P</S2SCTScf:TstCode>
<S2SCTScf:FType>SCF</S2SCTScf:FType>
<S2SCTScf:FileRef>NSCT220610000729</S2SCTScf:FileRef>
<S2SCTScf:RoutingInd>IND</S2SCTScf:RoutingInd>
<S2SCTScf:FileBusDt>2022-06-10</S2SCTScf:FileBusDt>
<S2SCTScf:FileCycleNo>11</S2SCTScf:FileCycleNo>
<S2SCTScf:FIToFICstmrCdtTrf xmlns="urn:iso:std:iso:20022:tech:xsd:pacs.008.001.02">
<GrpHdr>
<MsgId>NSCT2206100007290000000000000000001</MsgId>
<CreDtTm>2022-06-10T09:52:54</CreDtTm>
</GrpHdr>
</S2SCTScf:FIToFICstmrCdtTrf>
</S2SCTScf:SCTScfBlkCredTrf>') FROM DUAL;
Outputs:
XMLNS_ELEMENT
<S2SCTScf:FIToFICstmrCdtTrf xmlns:S2SCTScf="urn:S2SCTScf:xsd:$SCTScfBlkCredTrf" xmlns="urn:iso:std:iso:20022:tech:xsd:pacs.008.001.02"/>
db<>fiddle here
As this and the XML in your previous question both have the GrpHdr node, and you were trying to the MsgId from it then, you might simply be trying to get the namespace so you can pass it back into another XMLQuery call.
If that is the case then you could ignore the namespaces and use wildcards:
with q1 (Tdata) as (
SELECT XMLtype(transportdata, nls_charset_id('AL32UTF8')) from paymentinterchange
)
select XMLQuery('//*:GrpHdr/*:MsgId/text()'
passing Tdata
returning content).getstringval()
from q1
which would get the message ID from this XML or the previous example. I've changed the character set to AL32UTF8 to match this XML's UTF-8 declaration, which could be a problem if you have a mix of encodings in your data.
db<>fiddle with the old and new XML.

Snowflake Get value from XML column

I am working in Snowflake
I need a specific value from XML
SELECT data_xml,REGEXP_SUBSTR(data_xml,'<pinLessNetworkBin>(.*?)(</pinLessNetworkBin>)',3) as network
FROM "DW"."DB"."TABLE"
My results for now
<pinLessNetworkBin>STAR</pinLessNetworkBin>
I just need the value inside
Here the xml:
<?xml version="1.0" encoding="UTF-8"?>
<ns0:FundingSource xmlns:ns0="www.url.com/be/example/payments/model/Concepts/FundingSource" Id="12887819260" extId="">
<id>3939</id>
<pinLessNetworkBin>STAR</pinLessNetworkBin>
</ns0:FundingSource>
How I can get that value?
Regards
the contents of an XML object is retrieved via GET(object, '$') thus for your regex result GET(parse_xml(network), '$') will get you the content. See GET
or you should really retrieve the pinLessNetworkBin via XMLGET:
SELECT data_xml,
XMLGET(parse_xml(data_xml), 'pinLessNetworkBin') as pinLessNetworkBin
FROM "DW"."DB"."TABLE"
parse_xml(data_xml)
which will give you the <pinLessNetworkBin>STAR</pinLessNetworkBin> thus you want to fetch the contents
SELECT data_xml,
get(XMLGET(parse_xml(data_xml), 'pinLessNetworkBin'), '$') as pinLessNetworkBin
FROM "DW"."DB"."TABLE"
parse_xml(data_xml)
should give you 'STAR'
see the PARSE_XML

exporting xml value from CLOB data field in oracle using multiple namespace

I have a table which contains x number of records. One of the fields is a CLOB and contains XML with a particular field
Here is a very shortened version of the XML
<metadata xml:lang="en"
xmlns:gmd="http://www.isotc211.org/2005/gmd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:gco="http://www.isotc211.org/2005/gco" xmlns:srv="http://www.isotc211.org/2005/srv" xmlns:gts="http://www.isotc211.org/2005/gts" xmlns:gml="http://www.opengis.net/gml" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:msxsl="urn:schemas-microsoft-com:xslt">
<gmd:GEMINI_Metadata>
<gmd:fileIdentifier>
<gco:CharacterString>cf40a39a-0721-4fd4-84f3-adc28aee1158</gco:CharacterString>
</gmd:fileIdentifier>
<gmd:dateStamp>
<gco:Date>2019-01-16</gco:Date>
</gmd:dateStamp>
</gmd:GEMINI_Metadata>
</metadata>
What I would like to do is get characterstring value from the fileIdentifier tag using SQL
I have tried the following
select EXTRACT (XMLType (DOCUMENTATION), '//fileIdentifier//gco:CharacterString','xmlns:gmd="http://www.isotc211.org/2005/gmd"', 'xmlns:gco="http://www.isotc211.org/2005/gco"') as DOCUMENTATION from sde.gdb_items_vw where name = 'testTable'
i get the following
ORA-00939: too many arguments for function
If I try only specifying one tag and one namespace like this
select EXTRACT (XMLType (DOCUMENTATION), '//gmd:fileIdentifier','xmlns:gmd="http://www.isotc211.org/2005/gmd"') as DOCUMENTATION from sde.gdb_items_vw where name = 'testTable';
I get the following
DOCUMENTATION
--------------------------------------------------------------------------------
<gmd:fileIdentifier xmlns:gmd="http://www.isotc211.org/2005/gmd"><gco:CharacterS
So what is the correct way of getting a particular tag that has multiple namespaces within its tree?
The best method is to use XMLTABLE. Here you can easily specify the namespaces.
SELECT doc AS documentation
FROM sde.gdb_items_vw,
XMLTABLE( xmlnamespaces( 'http://www.isotc211.org/2005/gmd' AS "gmd",
'http://www.w3.org/2001/XMLSchema-instance' AS "xsi",
'http://www.isotc211.org/2005/gco' AS "gco",
'http://www.isotc211.org/2005/srv' AS "srv",
'http://www.isotc211.org/2005/gts' AS "gts",
'http://www.opengis.net/gml' AS "gml",
'http://www.w3.org/1999/xlink' AS "xlink",
'urn:schemas-microsoft-com:xslt' AS "msxsl"
),
'/metadata' PASSING XMLTYPE(documentation)
COLUMNS doc VARCHAR2(1000) PATH 'gmd:fileIdentifier/gco:CharacterString'
);
Result:
DOCUMENTATION
------------------------------------
cf40a39a-0721-4fd4-84f3-adc28aee1158

How to filter data from xml content using xpath queries to create a temporary table

I am trying to create a sql query using xpath where i am looking to filter the data i need and put that in a temporary table.
Example:
<superStarsDoc>
<names>
<starname>
<preferredname>pref</preferredname>
<firstNm>Bradd</firstNm>
<lastNm>Pitt</lastNm>
</starname>
</names>
</superStarsDoc>
and i am trying to get something like this but not working
with data(firstName,lastName) as
(
unnest(xpath('/superStarsDoc/names/starname/firstNm[#firstNm="Bradd"]/text()',
(select xmlparse(document superstar_doc))))::text as firstName
,unnest(xpath('/superStarsDoc/names/starname/lastNm[#lastNm="Pitt"]lastNm="/text()',
(select xmlparse(document superstar_doc))))::text as lastName
from dbname.superstartable
)
I tried searching for solution but i did not find anything specific for my requirement, i dont have any attribute to point to that record exactly.
I tried using the following solution but that is not working, i am getting syntax error.
XPath 1.0 to find if an element's value is in a list of values
Note: I typed the code here as i cannot copy paste my code exactly, so please excuse any typos
You should probably fix your XPath with :
/superStarsDoc/names/starname/firstNm[.="Bradd"]/text()
/superStarsDoc/names/starname/lastNm[.="Pitt"]/text()
Generic code :
with superstartable(superstar_doc) as (
values (
'<?xml version="1.0" encoding="UTF-8"?>
<superStarsDoc>
<names>
<starname>
<preferredname>pref</preferredname>
<firstNm>Bradd</firstNm>
<lastNm>Pitt</lastNm>
</starname>
</names>
</superStarsDoc>
'::xml)
)
SELECT
xpath('/superStarsDoc/names/starname/firstNm[.="Bradd"]/text()', superstar_doc)[1] as "first-name",
xpath('/superStarsDoc/names/starname/lastNm[.="Pitt"]/text()', superstar_doc)[1] as "last-name"
from superstartable

How to query xml value inside a xml column in SQL server

I have something like following code inside [XMLValue] column of a table called "AlgorithmLog":
<?xml version="1.0" encoding="utf-8"?>
<AdapterInfo xmlns:i="http://www.w3.org/2001/XMLSchema-instance"
xmlns:d1p1="http://schemas.datacontract.org/2004/07/Adapters.Adapter.CloudTrader"
xmlns="http://schemas.datacontract.org/2004/07/Adapters.Adapter"
i:type="d1p1:AlgorithmStatusReport">
<SequenceNumber>0</SequenceNumber>
<TrackingGuid i:nil="true" />
<d1p1:Broker>Default</d1p1:Broker>
...
<d1p1:XMLValue><?xml version="1.0"?><int xmlns="http://schemas.microsoft.com/2003/10/Serialization/">1900</int></d1p1:XMLValue>
</AdapterInfo>
and I want to get the value "1900" inside the node <d1p1:XMLValue>
So here is my query:
WITH XMLNAMESPACES('http://schemas.datacontract.org/2004/07/Adapters.Adapter' AS x,
'http://schemas.datacontract.org/2004/07/Adapters.Adapter.CloudTrader' As p,
'http://schemas.microsoft.com/2003/10/Serialization/'as w)
SELECT
XMLValue.query('(/x:AdapterInfo/p:XMLValue/w:int)[1]')AS [XMLVaule]
FROM AlgorithmLog
But it returns nothing.
Could anyone tell me where I did wrong or how I can do it?
Thank you.
Since you have "encoded" XML inside another XML node, and you cannot automatically cast to the XML datatype using the .value() XQuery method, it all gets a bit involved - but this seems to work for me:
;WITH XMLNAMESPACES('http://schemas.datacontract.org/2004/07/Adapters.Adapter' AS x,
'http://schemas.datacontract.org/2004/07/Adapters.Adapter.CloudTrader' As p,
'http://schemas.microsoft.com/2003/10/Serialization/'as w)
SELECT
CAST(XmlContent.value('(/x:AdapterInfo/p:XMLValue)[1]', 'varchar(2000)') AS XML).value('(w:int)[1]', 'int') AS [XMLValue]
FROM AlgorithmLog
WHERE ....... -- use whatever condition makes sense for you here