how to access value of XML - sql-server

SQL Server 2012
How to access "datefrom" value from below XML? Have try almost everything but without success :(
<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://www.w3.org/2003/05/soap-envelope">
<SOAP-ENV:Body>
<ns0:getInterestAndExchangeRatesResponse xmlns:ns0="http://swea.riksbank.se/xsd">
<return>
<datefrom>2020-03-05</datefrom>
<dateto>2020-03-05</dateto>
</return>
</ns0:getInterestAndExchangeRatesResponse>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>

You need to respect the XML namespaces in play - but once you do, this should work for you:
DECLARE #Data XML = '....(your XML here).....';
-- define the two XML namespaces in play
WITH XMLNAMESPACES('http://www.w3.org/2003/05/soap-envelope' AS soap,
'http://swea.riksbank.se/xsd'AS ns)
SELECT
#Data.value('(soap:Envelope/soap:Body/ns:getInterestAndExchangeRatesResponse/return/datefrom)[1]', 'varchar(20)')
This will return something like:
2020-03-05

Related

Get XML Value from SOAP Request Stored in SQL Server 2014

I have the below SOAP that is stored in an XML column in SQL and I am looking for a way to fetch a specific value. An example of the SOAP is as follows. This is a snippet of a way larger request.
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
<s:Header>
<Action xmlns="http://schemas.microsoft.com/ws/2005/05/addressing/none" s:mustUnderstand="1">http://xyzservice/submit</Action>
</s:Header>
<s:Body xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<serviceAuthorization xmlns="http://www.xyzservice.com/xyzz/schema/auth">
<recordType xmlns="">Authorization</recordType>
<externalAuthorizationId xmlns="">4</externalAuthorizationId>
<authorizationStatus xmlns="">APPROVED</authorizationStatus>
</serviceAuthorization>
</s:Body>
</s:Envelope>
The SQL I am using is as follows. I have tried it a few different ways, but still no luck. Any help would be appreciated. I have found very few resources that cover what I am trying to do.
WITH XMLNAMESPACES
('http://schemas.xmlsoap.org/soap/envelope/' AS s)
select
REQUEST_XML.query('/s:Envelope/s:Body/serviceAuthorization/recordType/*')
FROM HE_EXTRACT_HISTORY
WHERE REQUEST_XML IS NOT NULL
Here ya go, I tested this locally in SQL Server 2014:
SELECT a.value('recordType[1]', 'varchar(100)')
FROM REQUEST_XML.nodes('//*:serviceAuthorization') AS xx(a)

How do I convert SQL to XML?

I am trying to output SQL as XML to match the exact format as the following
<?xml version="1.0" encoding="utf-8"?>
<ProrateImport xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://schema.aldi-
sued.com/Logistics/Shipping/ProrateImport/20151009">
<Prorates>
<Prorate>
<OrderTypeId>1</OrderTypeId>
<DeliveryDate>2015-10-12T00:00:00+02:00</DeliveryDate>
<DivNo>632</DivNo>
<ProrateUnit>1</ProrateUnit>
<ProrateProducts>
<ProrateProduct ProductCode="8467">
<ProrateItems>
<ProrateItem StoreNo="1">
<Quantity>5</Quantity>
</ProrateItem>
<ProrateItem StoreNo="2">
<Quantity>5</Quantity>
</ProrateItem>
<ProrateItem StoreNo="3">
<Quantity>5</Quantity>
</ProrateItem>
</ProrateItems>
</ProrateProduct>
</ProrateProducts>
</Prorate>
</Prorates>
</ProrateImport>
Here is my query:
SELECT
OrderTypeID,
DeliveryDate, DivNo,
ProrateUnit,
(SELECT
ProductOrder [#ProductCode],
(SELECT
ProrateItem [#StoreNo],
CAST(Quantity AS INT) [Quantity]
FROM
##Result2 T3
WHERE
T3.DivNo = T2.DivNo
AND T3.DivNo = T1.DivNo
AND T3.DeliveryDate = T2.DeliveryDate
AND T3.DeliveryDate = T1.DeliveryDate
AND T3.ProductOrder = t2.ProductOrder
FOR XML PATH('ProrateItem'), TYPE, ROOT('ProrateItems')
)
FROM
##Result2 T2
WHERE
T2.DivNo = T1.DivNo
AND T2.DeliveryDate = T1.DeliveryDate
FOR XML PATH('ProrateProduct'), TYPE, ROOT('ProrateProducts')
)
FROM
##Result2 T1
GROUP BY
OrderTypeID, DeliveryDate, DivNo, ProrateUnit
FOR XML PATH('Prorate'), TYPE, ROOT('Prorates')
How do I add in the Following and have the ProrateImport/20151009" change to the current date?
<?xml version="1.0" encoding="utf-8"?>
<ProrateImport xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://schema.aldi-
sued.com/Logistics/Shipping/ProrateImport/20151009">
This is my first time I have used XML
Im not sure i understand. Did you create the first XML yourself and just need to add the last script?
DECLARE #XMLHEADER nvarchar(max)
SET #XMLHEADER = '<?xml version="1.0" encoding="utf-8"?>
<ProrateImport xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://schema.aldi-sued.com/Logistics/Shipping/ProrateImport/'+convert(varchar(8),getdate(),112)+'"
>'
select #xmlheader
And then you just need to add the rest of your output from your select statement.
There are several problems:
How to introduce namespaces?
How to introduce namespaces dynamically
How to add a <?xml ?> directive
two-leveled root (<ProrateImport><Prorate>)
namespaces
You have to use WITH XMLNAMESSPACES to introduce a namespace to your query.
Hint: the naked xmlns is introduced by DEFAULT, the xsi namespace will be introduced automatically by using ELEMENTS XSINIL:
WITH XMLNAMESPACES('http://www.w3.org/2001/XMLSchema' AS xsd
,DEFAULT 'http://schema.aldi-sued.com/Logistics/Shipping/ProrateImport/20151009')
SELECT 1 AS Dummy
FOR XML PATH('rowElement'), ELEMENTS XSINIL, ROOT('root')
The result
<root xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://schema.aldi-sued.com/Logistics/Shipping/ProrateImport/20151009"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<rowElement>
<Dummy>1</Dummy>
</rowElement>
</root>
Note: The namespaces must be stated literally. No computations, no variables!
dynamic namespaces
This is - out of the box - impossible. But you might use dynamically created SQL and use EXEC to get your result. Just create exactly the statement as above
DECLARE #cmd VARCHAR(MAX)=
'
WITH XMLNAMESPACES(''http://www.w3.org/2001/XMLSchema'' AS xsd
,DEFAULT ''http://schema.aldi-sued.com/Logistics/Shipping/ProrateImport/' + CONVERT(VARCHAR(8),GETDATE(),112) + ''')
SELECT 1 AS Dummy
FOR XML PATH(''rowElement''), ELEMENTS XSINIL, ROOT(''root'')';
PRINT #cmd
EXEC(#cmd);
the result
<root xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://schema.aldi-sued.com/Logistics/Shipping/ProrateImport/20171019"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<rowElement>
<Dummy>1</Dummy>
</rowElement>
</root>
directive
The directive cannot be introduced into XML. SQL-Server will omit any <?xml ?> directive! This can only be done on string level:
DECLARE #cmd VARCHAR(MAX)=
'
WITH XMLNAMESPACES(''http://www.w3.org/2001/XMLSchema'' AS xsd
,DEFAULT ''http://schema.aldi-sued.com/Logistics/Shipping/ProrateImport/' + CONVERT(VARCHAR(8),GETDATE(),112) + ''')
SELECT(
SELECT 1 AS Dummy
FOR XML PATH(''rowElement''), ELEMENTS XSINIL, ROOT(''root'')) AS MyResult';
CREATE TABLE #resultTable(MyXmlAsString VARCHAR(MAX))
INSERT INTO #resultTable(MyXmlAsString)
EXEC(#cmd);
SELECT '<?xml version="1.0" encoding="utf-8"?>' + MyXmlAsString
FROM #resultTable;
The result
<?xml version="1.0" encoding="utf-8"?>
<root xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://schema.aldi-sued.com/Logistics/Shipping/ProrateImport/20171019"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<rowElement>
<Dummy>1</Dummy>
</rowElement>
</root>
two-leveled root
You can nest two FOR XML statements to achieve this:
WITH XMLNAMESPACES(DEFAULT 'blah')
SELECT
(
SELECT 1 AS Dummy
FOR XML PATH('rowElement'),ROOT('innerRoot'),TYPE
)
FOR XML PATH('outerRoot');
But the annoying part is, that namespaces are introduced by each sub-select over and over. Not wrong but very annoying! A well known Microsoft connect issue. Please sign in and vote for it! The result:
<outerRoot xmlns="blah">
<innerRoot xmlns="blah"> <!--Here's the second xmlns! -->
<rowElement>
<Dummy>1</Dummy>
</rowElement>
</innerRoot>
</outerRoot>
Your solution
After explained all this I'd suggest to create the XML without any namespace or declaration (what you are doing already!), then convert the result to NVARCHAR(MAX) and add the header and the closing footer on string level. This is ugly, but in your case the only way.
Hint: You will not be able to store the final result in a native XML type in SQL Server without loosing the directive.

How to get data from XML Column that contain xml namespace (SQL Server 2005)

I google a lot and got no luck.
I can't retrieve data from XML column which data came from web service using sp_OAGetProperty.
the XML Column contain..
<ArrayOfCustomerInfo xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://tempuri.org/">
<Customer CustCode="001">
<CustName>John</CustName>
<Queues>
<Q>
<No>10</No>
<Line>1</Line>
</Q>
</Queues>
</Customer>
</ArrayOfCustomerInfo>
I got NULL when I execute following statement
(but works fine if I remove all XML namespace xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://tempuri.org/")
SELECT a.b.value('#CustCode','varchar(4)') AS Code
,a.b.value('CustName[1]','varchar(20)') AS Name
,c.d.value('No[1]','int') AS QNo
,c.d.value('(Line)[1]','int') AS QLine
FROM PGHRMS_Employees x
CROSS APPLY x.data.nodes('/ArrayOfCustomerInfo/Customer') AS a(b)
CROSS APPLY a.b.nodes('Queues/Q') AS c(d)
please give me some advice. I've to achieve with SQL SERVER :(
If anyone want to reproduce it, I pasted script at : http://pastebin.com/ueZGidyL
Thank you in advance !!!
Try this:
;WITH XMLNAMESPACES(DEFAULT 'http://tempuri.org/')
SELECT
Code = XC1.value('#CustCode', 'varchar(4)'),
Name = XC1.value('CustName[1]', 'varchar(20)'),
QNo = XC2.value('No[1]', 'int') ,
QLine = XC2.value('(Line)[1]','int')
FROM
PGHRMS_Employees
CROSS APPLY
XmlContent.nodes('/ArrayOfCustomerInfo/Customer') AS XT1(XC1)
CROSS APPLY
XC1.nodes('Queues/Q') AS XT2(XC2)
With the WITH XMLNAMESPACES construct, you can define some XML namespaces to be used by the following T-SQL statement - default or prefixed namespaces alike.

T-SQL Xquery Exist Method return nothing

I have the following xquery piece, I'm trying to test outside of my t-sql script:
DECLARE #x XML
SELECT #x = N'<?xml version="1.0" encoding="utf-16"?>
<Root xmlns="http://www.w3.org">
<Header>
<Record>
<A99>
<A99_01_0>
<A99_01>TEST</A99_01>
<A99_02>TEST</A99_02>
<A99_03>TEST</A99_03>
</A99_01_0>
</A99>
</Record>
</Header>
</Root>
';
select #x.exist('//Header/Record/A99/A99_01_0/A99_01')
I simply want to check if there is a value between the A99_01 tags, which there is. But according to my exist(), my output keeps coming back as 0, indicating that it doesn't exist.
Is there something I'm missing? I've double checked to make sure my syntax for the exist() is correct. Any help would be greatly appreciated!
Yes - you're missing the XML namespace defined in your XML document!
SELECT #x = N'<?xml version="1.0" encoding="utf-16"?>
<Root xmlns="http://www.w3.org">
*************************
You need to change your SELECT to:
WITH XMLNAMESPACES(DEFAULT 'http://www.w3.org')
SELECT
#x.exist('//Header/Record/A99/A99_01_0/A99_01')

Extract XML header information into SQL server

My process involves getting a large XML file on a daily basis.
I have developed an SSIS package (2008 r2) which first gets rid of the multiple namespaces via a XSLT and then imports data into 40 tables (due to its complexity) by using the XML source object.
Here is the watered down version of a test xml file
<?xml version="1.0" encoding="UTF-8"?>
<s:Test xmlns:s="http://###.##.com/xml"
<sequence>62</sequence>
<generated>2015-04-28T00:59:38</generated>
<report_date>2015-04-27</report_date>
<orders>
<order>
</order>
</orders>
My question is: The XML source imports all the Orders with its nested attributes. How do I extract the 'report_date' and 'generated' from the header?
Any help would be much appreciated.
Thanks
SD
You can use XML method value() passing proper XPath/XQuery expression as parameter. For demo, consider the following table and data :
CREATE TABLE MyTable (id int, MyXmlColumn XML)
DECLARE #data XML = '<?xml version="1.0" encoding="UTF-8"?>
<s:Test xmlns:s="http://###.##.com/xml">
<sequence>62</sequence>
<generated>2015-04-28T00:59:38</generated>
<report_date>2015-04-27</report_date>
<orders>
<order>
</order>
</orders>
</s:Test>'
INSERT INTO Mytable VALUES(1,#data)
You can use the following query to get generated and report_date data :
SELECT
t.MyXmlColumn.value('(/*/generated)[1]','datetime') as generated
, t.MyXmlColumn.value('(/*/report_date)[1]','date') as report_date
FROM Mytable t
SQL Fiddle Demo
output :
generated report_date
----------------------- -----------
2015-04-28 00:59:38.000 2015-04-27

Resources