ORA-19228: XPST0008 - undeclared identifier in oracle sql - sql

I have xml string which i have mentioned below and i want to extract code from xml string. I have written below select query to extract the value from <ax2140:code>0</ax2140:code> which is 0 but i am getting error as
ORA-19228: XPST0008 - undeclared identifier: prefix 'ax2140' local-name 'ax2140:code'
19228. 00000 - "XPST0008 - undeclared identifier: prefix '%s' local-name '%s'"
Here is my xml string-
<?xml version="1.0" encoding="UTF-8"?>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<soapenv:Body>
<ns:placeShopOrderResponse xmlns:ns="http://service.soap.CDRator.com">
<ns:return xmlns:ax2127="http://data.soap.CDRator.com/xsd"
xmlns:ax2129="http://webshop.data.soap.CDRator.com/xsd"
xmlns:ax2130="http://core.data.soap.CDRator.com/xsd"
xmlns:ax2133="http://signup.data.soap.CDRator.com/xsd"
xmlns:ax2134="http://core.signup.data.soap.CDRator.com/xsd"
xmlns:ax2139="http://result.service.soap.CDRator.com/xsd"
xmlns:ax2140="http://core.result.service.soap.CDRator.com/xsd"
xmlns:ax2147="http://webshop.result.service.soap.CDRator.com/xsd"
xmlns:ax2148="http://mandate.result.service.soap.CDRator.com/xsd"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="ax2147:PlaceShopOrderResultDTO">
<ax2130:id xsi:nil="true" />
<ax2140:code>0</ax2140:code>
<ax2140:description>OK</ax2140:description>
<ax2127:statusId>1</ax2127:statusId>
<ax2127:subscriptionCondition xsi:type="ax2127:SubscriptionStatusDTO">
<ax2130:id xsi:nil="true" />
<ax2140:code>0</ax2140:code>
<ax2140:description>OK</ax2140:description>
<ax2130:imsi xsi:nil="true" />
<ax2130:phoneNumber>NO_NUMBER</ax2130:phoneNumber>
<ax2127:imei xsi:nil="true" />
<ax2127:simCard xsi:nil="true" />
</ax2127:teleService>
</ax2147:subscriptions>
</ns:return>
</ns:placeShopOrderResponse>
</soapenv:Body>
</soapenv:Envelope>
Here is my select query:
SELECT ID,xt_code.CODE
FROM TEMP_SOAP_MONITORING_MSP sm
CROSS JOIN XMLTable(XMLNAMESPACES (
'http://core.result.service.soap.CDRator.com/xsd' as "ax2140_code"
),
'for $i in //ax2140:code return $i'
passing XMLType(sm.RESPONSE_XML)
columns "CODE" VARCHAR2(50) path '/') xt_code;

Use "ax2140" instead of "ax2140_code" in the query.

Related

Extracting XML data using SQL

I would like to be able to extract specific data from a XML type using Oracle in my example for the customer named "Arshad Ali"
This is my xml data that was inserted:
<Customers>
<Customer CustomerName="Arshad Ali" CustomerID="C001">
<Orders>
<Order OrderDate="2012-07-04T00:00:00" OrderID="10248">
<OrderDetail Quantity="5" ProductID="10" />
<OrderDetail Quantity="12" ProductID="11" />
<OrderDetail Quantity="10" ProductID="42" />
</Order>
</Orders>
<Address> Address line 1, 2, 3</Address>
</Customer>
<Customer CustomerName="Paul Henriot" CustomerID="C002">
<Orders>
<Order OrderDate="2011-07-04T00:00:00" OrderID="10245">
<OrderDetail Quantity="12" ProductID="11" />
<OrderDetail Quantity="10" ProductID="42" />
</Order>
</Orders>
<Address> Address line 5, 6, 7</Address>
</Customer>
<Customer CustomerName="Carlos Gonzlez" CustomerID="C003">
<Orders>
<Order OrderDate="2012-08-16T00:00:00" OrderID="10283">
<OrderDetail Quantity="3" ProductID="72" />
</Order>
</Orders>
<Address> Address line 1, 4, 5</Address>
</Customer>
</Customers>
</ROOT>
using get clob I was able to extract all of the customers.
Was wondering if anyone could help me extract data for a specific customer.. tried using the following but was unsuccessful
SELECT extract(OBJECT_VALUE, '/root/Customers') "customer"
FROM mytable2
WHERE existsNode(OBJECT_VALUE, '/customers[CustomerName="Arshad Ali" CustomerID="C001"]')
= 1;
The case and exact names of the XML nodes matter:
SELECT extract(OBJECT_VALUE,
'/ROOT/Customers/Customer[#CustomerName="Arshad Ali"][#CustomerID="C001"]') "customer"
FROM mytable2
WHERE existsnode (OBJECT_VALUE,
'/ROOT/Customers/Customer[#CustomerName="Arshad Ali"][#CustomerID="C001"]') = 1
db<>fiddle
If you only want to search by name then only use that attribute:
SELECT extract(OBJECT_VALUE,
'/ROOT/Customers/Customer[#CustomerName="Arshad Ali"]') "customer"
FROM mytable2
WHERE existsnode (OBJECT_VALUE,
'/ROOT/Customers/Customer[#CustomerName="Arshad Ali"]') = 1
But extract() and existsnode() are deprecated; use xmlquery() and xmlexists() instead:
SELECT xmlquery('/ROOT/Customers/Customer[#CustomerName="Arshad Ali"][#CustomerID="C001"]'
passing object_value
returning content) "customer"
FROM mytable2
WHERE xmlexists('/ROOT/Customers/Customer[#CustomerName="Arshad Ali"][#CustomerID="C001"]'
passing object_value)
db<>fiddle

Create Smaller XML based on value of element

On Python 3.7, I am looking to create a subset of a XML. For example, the larger XML is:
<data>
<student>
<result>
<grade>A</grade>
</result>
<details>
<name>John</name>
<id>100</id>
<age>16</age>
<email>john#mail.com</email>
</details>
</student>
<student>
<result>
<grade>B</grade>
</result>
<details>
<name>Alice</name>
<id>101</id>
<age>17</age>
<email>alice#mail.com</email>
</details>
</student>
<student>
<result>
<grade>F</grade>
</result>
<details>
<name>Bob</name>
<id>102</id>
<age>16</age>
<email>bob#mail.com</email>
</details>
</student>
<student>
<result>
<grade>A</grade>
</result>
<details>
<name>Hannah</name>
<id>103</id>
<age>17</age>
<email>hannah#mail.com</email>
</details>
</student>
</data>
and am looking for a new XML like below, the condition to create a smaller subset depends on a list of ids in this case 101 and 102. All other student blocks will be deleted.
<data>
<student>
<result>
<grade>B</grade>
</result>
<details>
<name>Alice</name>
<id>101</id>
<age>17</age>
<email>alice#mail.com</email>
</details>
</student>
<student>
<result>
<grade>F</grade>
</result>
<details>
<name>Bob</name>
<id>102</id>
<age>16</age>
<email>bob#mail.com</email>
</details>
</student>
</data>
i.e. The output XML will depend on a list of id's, in this case ['101',102']
This is what I tried:
import lxml.etree
#Original Large XML
tree = etree.parse(open('students.xml'))
root = tree.getroot()
results = root.findall('student')
textnumbers = [r.find('details/id').text for r in results]
print(textnumbers)
required_ids = ['101','102']
wanted = tree.xpath("//student/details/[not(#id in required_ids)]")
for node in unwanted:
node.getparent().remove(node)
#New Smaller XML
tree.write(open('student_output.xml', 'wb'))
But I am getting an expected error of "Invalid expression" for
wanted = tree.xpath("//student/details/[not(#id in required_ids)]")
I know it's a read, but i am fairly new to Python, thanks in advance for your help.
I think you can do it like this:
from lxml import etree as ET
required_ids = ['101','102']
for event, element in ET.iterparse('students.xml'):
if element.tag == 'student' and not(element.xpath('.//id/text()')[0] in required_ids):
element.clear()
element.getparent().remove(element)
if element.tag == 'data':
ET.dump(element)
Instead of the dump you would of course want to write to a file, that is use
if element.tag == 'data':
tree = ET.ElementTree(element)
tree.write('student_output.xml')
Your attempt fails as you can't simply use a Python list variable in XPath and in is not an XPath 1.0 operator.

XPath doesn't provide proper tag

I'm trying to get tag "" from xml below.
If i execute request like this:
WITH x(col) AS (select'<document xmlns="http://example.com/digital/back/" xmlns:ns2="http://example.com/digital/back/complexId" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="">
<header>
<docId>13a2f29a28b12ecb</docId>
<dt>2018-12-10T11:59:48.112+03:00</dt>
</header>
<pay>
<reqTransfer id="154638">
<source>
<card>
<virtualCardNum>4B74C1EE187</virtualCardNum>
<bsc>VISA</bsc>
</card>
</source>
</reqTransfer>
</pay>
</document>
'::xml)
SELECT xpath('/document/pay/reqTransfer/source/card/bsc/text()', col) AS bsc
FROM x;
I get {}, but if I relpace the document start tag
<document xmlns="http://example.com/digital/back/" xmlns:ns2="http://example.com/digital/back/complexId" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="">
with <document> or even <document xmlns="">, I get { VISA } - that is right.
What should I do to replace <document xmlns="..."> with <document> or get { VISA } without replacement?
If you are working with XML namespaces, they are worth mentioning in your Xpath queries too, i.e. use
SELECT xpath('/d:document/d:pay/d:reqTransfer/d:source/d:card/d:bsc/text()', col,
ARRAY[ARRAY['d', 'http://example.com/digital/back/']]) AS bsc
http://sqlfiddle.com/#!17/9eecb/24719
See also:
how to ignore namespaces with XPath

Find element or attribute value anywhere in XML

I am trying to find the value of an element / attribute regardless of where it exists in the XML.
XML:
<?xml version="1.0" encoding="UTF-8"?>
<cXML payloadID="12345677-12345567" timestamp="2017-07-26T09:11:05">
<Header>
<From>
<Credential domain="1212">
<Identity>01235 </Identity>
<SharedSecret/>
</Credential>
</From>
<To>
<Credential domain="1212">
<Identity>01234</Identity>
</Credential>
</To>
<Sender>
<UserAgent/>
<Credential domain="8989">
<Identity>10678</Identity>
<SharedSecret>Testing123</SharedSecret>
</Credential>
</Sender>
</Header>
<Request deploymentMode="Prod">
<ConfirmationRequest>
<ConfirmationHeader noticeDate="2017-07-26T09:11:05" operation="update" type="detail">
<Total>
<Money>0.00</Money>
</Total>
<Shipping>
<Description>Delivery</Description>
</Shipping>
<Comments>WO# generated</Comments>
</ConfirmationHeader>
<OrderReference orderDate="2017-07-25T15:22:11" orderID="123456780000">
<DocumentReference payloadID="5678-4567"/>
</OrderReference>
<ConfirmationItem quantity="1" lineNumber="1">
<ConfirmationStatus quantity="1" type="detail">
<ItemIn quantity="1">
<ItemID>
<SupplierPartID>R954-89</SupplierPartID>
</ItemID>
<ItemDetail>
<UnitPrice>
<Money currency="USD">0.00</Money>
</UnitPrice>
<Description>Test Descritpion 1</Description>
<UnitOfMeasure>QT</UnitOfMeasure>
</ItemDetail>
</ItemIn>
</ConfirmationStatus>
</ConfirmationItem>
<ConfirmationItem quantity="1" lineNumber="2">
<ConfirmationStatus quantity="1" type="detail">
<ItemIn quantity="1">
<ItemID>
<SupplierPartID>Y954-89</SupplierPartID>
</ItemID>
<ItemDetail>
<UnitPrice>
<Money currency="USD">0.00</Money>
</UnitPrice>
<Description>Test Descritpion 2</Description>
<UnitOfMeasure>QT</UnitOfMeasure>
</ItemDetail>
</ItemIn>
</ConfirmationStatus>
</ConfirmationItem>
</ConfirmationRequest>
</Request>
</cXML>
I want to get the value of the payloadID on the DocumentReference element. This is what I have tried so far:
BEGIN
Declare #Xml xml
Set #Xml = ('..The XML From Above..' as xml)
END
--no value comes back
Select c.value('(/*/DocumentReference/#payloadID)[0]','nvarchar(max)') from #Xml.nodes('//cXML') x(c)
--no value comes back
Select c.value('#payloadID','nvarchar(max)') from #Xml.nodes('/cXML/*/DocumentReference') x(c)
--check if element exists and it does
Select #Xml.exist('//DocumentReference');
I tried this in an xPath editor: //DocumentReference/#payloadID
This does work, but I am not sure what the equivalent syntax is in SQL
Calling .nodes() (like suggested in comment) is an unecessary overhead...
Better try it like this:
SELECT #XML.value('(//DocumentReference/#payloadID)[1]','nvarchar(max)')
And be aware, that XPath starts counting at 1. Your example with [0] cannot work...
--no value comes back
Select c.value('(/*/DocumentReference/#payloadID)[0]','nvarchar(max)') from...

Extract proper data from a sql server XML column using XQuery

I am having an issue trying to get proper data from an XML type column:
"<"ArrayOfAccountInformation xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.Balance.com/">
"<"AccountInformation>
"<"AccountNumber xmlns="https://Safouenmzah.com/">0100000000"<"/AccountNumber>
"<"OutstandingAmount xmlns="https://Safouenmzah.com/">-909.55"<"/OutstandingAmount>
"<"LastBilledAmount xmlns="https://Safouenmzah.com/" />
"<"LastPaidDate xmlns="https://Safouenmzah.com/" />
"<"Severance xmlns="https://Safouenmzah.com/" />
"<"PaymentAmount xmlns="https://Safouenmzah.com/" />
"<"DistributedAmount xmlns="https://Safouenmzah.com/">$"<"/DistributedAmount>
"<"AccountInfo xmlns="https://Safouenmzah.com/">Safouen Mzah - Residential"<"/AccountInfo>
"<"/AccountInformation>
"<"/ArrayOfAccountInformation>
I am using this sql code:
;WITH XMLNAMESPACES ('http://www.Balance.com/' AS ns)
SELECT xmlResult.value('(/ns:ArrayOfAccountInformation)[1]','varchar(8000)') AS AcctInfo
FROM [dbo].[BalanceEnquiry_Transactions_Tracker]
WHERE BanlanceEnquiry_Transc_ID = 4
GO
This the result I am receiving always:
0100000000-909.55AEDSafouen Mzah - Residential
This is the expected result:
0100000000
Can some one help on this please?
Finally I figured it out.
declare #XML XML;
set #XML = '
"<"ArrayOfAccountInformation xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.Balance.com/">
"<"AccountInformation>
"<"AccountNumber xmlns="https://Safouenmzah.com/">0100000000"<"/AccountNumber>
"<"OutstandingAmount xmlns="https://Safouenmzah.com/">-909.55"<"/OutstandingAmount>
"<"LastBilledAmount xmlns="https://Safouenmzah.com/" />
"<"LastPaidDate xmlns="https://Safouenmzah.com/" />
"<"Severance xmlns="https://Safouenmzah.com/" />
"<"PaymentAmount xmlns="https://Safouenmzah.com/" />
"<"DistributedAmount xmlns="https://Safouenmzah.com/">$"<"/DistributedAmount>
"<"AccountInfo xmlns="https://Safouenmzah.com/">Safouen Mzah - Residential" <"/AccountInfo>
"<"/AccountInformation>
"<"AccountInformation>
"<"AccountNumber xmlns="https://Safouenmzah.com/">0200000000"<"/AccountNumber>
"<"OutstandingAmount xmlns="https://Safouenmzah.com/">-908.55"<"/OutstandingAmount>
"<"LastBilledAmount xmlns="https://Safouenmzah.com/" />
"<"LastPaidDate xmlns="https://Safouenmzah.com/" />
"<"Severance xmlns="https://Safouenmzah.com/" />
"<"PaymentAmount xmlns="https://Safouenmzah.com/" />
"<"DistributedAmount xmlns="https://Safouenmzah.com/">$"<"/DistributedAmount>
"<"AccountInfo xmlns="https://Safouenmzah.com/">Safouen Mzah - Expat"<"/AccountInfo>
"<"/AccountInformation>
"<"/ArrayOfAccountInformation>
'
;WITH XMLNAMESPACES ('http://www.Balance.com/' AS ns)
-- To get the outstanding amount of the first Account from the returned array
SELECT #XML.value('(/*[1]/*[1]/*[2])', 'varchar(200)') As OutstandingAmount1
-- To get the outstanding amount of the second Account from the returned array
SELECT #XML.value('(/*[1]/*[2]/*[2])', 'varchar(200)') As OutstandingAmount2
OutstandingAmount1
-909.55
OutstandingAmount2
-908.55
You can use nodes() to shred the XML and get the values in one resultset.
with xmlnamespaces('https://Safouenmzah.com/' as ns,
default 'http://www.Balance.com/')
select T.X.value('(ns:OutstandingAmount/text())[1]', 'varchar(200)')
from #XML.nodes('/ArrayOfAccountInformation/AccountInformation') as T(X)
SQL Fiddle