SQL Server : generating xml with security header for soap web service - sql-server

I have a task to create a procedure in SQL Server that can generate XML and communicate with a SOAP web service.
This is how the XML should look:
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:tem="http://tempuri.org/">
<soapenv:Header>
<wsse:Security soapenv:mustUnderstand="1" xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
<wsse:UsernameToken wsu:Id="UsernameToken-10788FB36F6242F7FE151731009896412">
<wsse:Username>username</wsse:Username>
<wsse:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText">password</wsse:Password>
<wsse:Nonce EncodingType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary">5/0ZUluzscbIlR5RcT6Rgg==</wsse:Nonce>
<wsu:Created>2018-01-30T11:01:38.963Z</wsu:Created>
</wsse:UsernameToken>
</wsse:Security>
</soapenv:Header>
<soapenv:Body>
<tem:GetTransportMethods>
<!--Optional:-->
<tem:Dealer_code>?</tem:Dealer_code>
</tem:GetTransportMethods>
</soapenv:Body>
</soapenv:Envelope>
Is there any possible way to regenerate this in SQL Server? Especially generate UsernameToken, Nonce and Created? Thanks

This code should create exactly the same XML as you posted above, with one difference: The places where the namespaces are declared. My code will place all declarations within the first-level node <soapenv:Envelope>. This is - semantically - the same as yours. But very strict validators might bark...
If you are forced to create it exactly as above you must use tricks on string level using REPLACE(), STUFF() and similar functions...
One word about ordering: The elements order within an XML is an implicit part of the document. But the order of attributes may be different! This is by definition!
WITH XMLNAMESPACES('http://schemas.xmlsoap.org/soap/envelope/' AS soapenv
,'http://tempuri.org/' AS tem
,'http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd' AS wsse
,'http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd' AS wsu)
SELECT 1 AS [soapenv:Header/wsse:Security/#soapenv:mustUnderstand]
,'UsernameToken-10788FB36F6242F7FE151731009896412' AS [soapenv:Header/wsse:Security/wsse:UsernameToken/#wsu:Id]
,'username' AS [soapenv:Header/wsse:Security/wsse:UsernameToken/wsse:Username]
,'http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText' AS [soapenv:Header/wsse:Security/wsse:UsernameToken/wsse:Password/#Type]
,'password' AS [soapenv:Header/wsse:Security/wsse:UsernameToken/wsse:Password]
,'http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary' AS [soapenv:Header/wsse:Security/wsse:UsernameToken/wsse:Nonce/#EncodingType]
,'5/0ZUluzscbIlR5RcT6Rgg==' AS [soapenv:Header/wsse:Security/wsse:UsernameToken/wsse:Nonce]
,'2018-01-30T11:01:38.963Z' AS [soapenv:Header/wsse:Security/wsse:UsernameToken/wsu:Created]
,'?' AS [soapenv:Body/tem:GetTransportMethods/tem:Dealer_code]
FOR XML PATH('soapenv:Envelope')
The result
<soapenv:Envelope xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"
xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"
xmlns:tem="http://tempuri.org/"
xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<soapenv:Header>
<wsse:Security soapenv:mustUnderstand="1">
<wsse:UsernameToken wsu:Id="UsernameToken-10788FB36F6242F7FE151731009896412">
<wsse:Username>username</wsse:Username>
<wsse:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText">password</wsse:Password>
<wsse:Nonce EncodingType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary">5/0ZUluzscbIlR5RcT6Rgg==</wsse:Nonce>
<wsu:Created>2018-01-30T11:01:38.963Z</wsu:Created>
</wsse:UsernameToken>
</wsse:Security>
</soapenv:Header>
<soapenv:Body>
<tem:GetTransportMethods>
<tem:Dealer_code>?</tem:Dealer_code>
</tem:GetTransportMethods>
</soapenv:Body>
</soapenv:Envelope>

Related

SQL Server 2019 FOR XML nested nodes preserving CDATA

I have to build this payload
<?xml version="1.0" encoding="utf-8"?>
<shipment>
<software>
<application>MYRTL</application>
<version>1.0</version>
</software>
<security>
<customer>X00000</customer>
<user>X00000</user>
<password>password1</password>
<langid>IT</langid>
</security>
<consignment action="I" cashondeliver="N" international="N" insurance="N">
<labelType>T</labelType>
<senderAccId>200200</senderAccId>
<consignmenttype>T</consignmenttype>
<actualweight>00008000</actualweight>
<actualvolume>0000018</actualvolume>
<totalpackages>2</totalpackages>
<packagetype>C</packagetype>
<division>D</division>
<product>N</product>
<insurancevalue>0000000000000</insurancevalue>
<insurancecurrency>EUR</insurancecurrency>
<reference><![CDATA[22X000223]]></reference>
<collectiondate>20220818</collectiondate>
<termsofpayment>S</termsofpayment>
<systemcode>RL</systemcode>
<systemversion>1.0</systemversion>
<codfvalue>0000000000000</codfvalue>
<codfcurrency>EUR</codfcurrency>
<goodsdesc><![CDATA[Bread, Butter & Puré]]></goodsdesc>
<addresses>
<address>
<addressType>S</addressType>
<vatno>123456789123</vatno>
<addrline1><![CDATA[Via Mondovì, n° 23]]></addrline1>
<postcode><![CDATA[20125]]></postcode>
<phone1><![CDATA[345]]></phone1>
<phone2><![CDATA[3456345]]></phone2>
<name><![CDATA[Jack & Joe srl]]></name>
<country><![CDATA[IT]]></country>
<town><![CDATA[Arquà Polesine]]></town>
<province><![CDATA[RO]]></province>
<email><![CDATA[mail#jack_and_joe.it]]></email>
</address>
<address>
<addressType>C</addressType>
<addrline1><![CDATA[12° Reggimento Granatieri, 14]]></addrline1>
<postcode><![CDATA[00195]]></postcode>
<phone1><![CDATA[321]]></phone1>
<phone2><![CDATA[3214321]]></phone2>
<name><![CDATA[Giosuè Rossë]]></name>
<country><![CDATA[IT]]></country>
<town><![CDATA[Gambolo']]></town>
<province><![CDATA[TV]]></province>
<email><![CDATA[mario#rossi.it]]></email>
</address>
<address>
<addressType>R</addressType>
<addrline1><![CDATA[Hauptstraße 13]]></addrline1>
<postcode><![CDATA[34100]]></postcode>
<phone1><![CDATA[333]]></phone1>
<phone2><![CDATA[333444555]]></phone2>
<name><![CDATA[Noè Giassù]]></name>
<country><![CDATA[IT]]></country>
<town><![CDATA[Völs am Schlern]]></town>
<province><![CDATA[BZ]]></province>
<email><![CDATA[mail#noe.it]]></email>
</address>
</addresses>
<collectiontrg>
<priopntime>0900</priopntime>
<priclotime>1200</priclotime>
<secopntime>1400</secopntime>
<secclotime>1800</secclotime>
<availabilitytime>1600</availabilitytime>
<pickupdate>18.08.2022</pickupdate>
<pickuptime>1600</pickuptime>
<pickupdays>1</pickupdays>
<pickupinstr><![CDATA[Test Shipment ===> DO NOT COLLECT <===]]></pickupinstr>
</collectiontrg>
<dimensions itemaction="I">
<itemsequenceno>1</itemsequenceno>
<itemtype>C</itemtype>
<itemreference><![CDATA[22X0002223_1]]></itemreference>
<volume>0000009</volume>
<weight>00003000</weight>
<length>030000</length>
<heigh>010000</heigh>
<width>030000</width>
<quantity>1</quantity>
</dimensions>
<dimensions itemaction="I">
<itemsequenceno>2</itemsequenceno>
<itemtype>C</itemtype>
<itemreference><![CDATA[22X0002223_2]]></itemreference>
<volume>0000009</volume>
<weight>00005000</weight>
<length>030000</length>
<heigh>010000</heigh>
<width>030000</width>
<quantity>1</quantity>
</dimensions>
</consignment>
</shipment>
I had the bad idea to use T-SQL since all data are in SQL Server DB
I thought it was quite easy, and actually, it was, since was just required to nest some FOR XML PATH, TYPE subqueries.
Problems arose when considered that some fields could contain not standard charachters, therefore was better to use some CDATA fields.
I faced several problems since it appears that the only way to preserve CDATA is using FOR XML EXPLICIT that seems to be deprecated.
However it was very difficult to find documentation.
Fortunately I found this post that helped me to make the reverse path:
Therefore I built a sproc with XML Explicit format:
SELECT 1 AS Tag,
NULL AS Parent,
'MYRTL' AS 'software!1!application!element',
'1.0' AS 'software!1!version!element',
NULL AS 'security!2!customer!element',
...
NULL AS 'security!2!langid!element',
NULL AS 'consignment!3!action',
...
NULL AS 'consignment!3!goodsdesc!CDATA',
NULL AS 'addresses!4!address',
NULL AS 'address!5!addressType!element',
...
NULL AS 'address!5!town!CDATA',
...
NULL AS 'collectiontrg!9!priopntime!element',
...
NULL AS 'collectiontrg!9!pickupdate!element',
UNION ALL
SELECT 2 AS Tag,
NULL AS Parent,
...
UNION ALL
SELECT 3 AS Tag,
NULL AS Parent,
...
UNION ALL
SELECT 9 AS Tag,
3 AS Parent,
...
FOR XML EXPLICIT, ROOT('shipment')
It seems to be working well... although I think there has to be a better way to build it.
Now I have a further issue that I do not know how to solve, or better, I could solve it using a dynamic query, but I would avoid it:
New issue is that node shipment.consignment.addresses.address where addressType=='C'
has to be omitted if it contains the same values as shipment.consignment.addresses.address where addressType=='S'
furthermore the node shipment.consignment.collectiontrg has to appear only if the variable pickupDate is not null
Is there a way to avoid the dynamic query?
Is there a better way to build this query?
Thanks

how to access value of XML

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

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)

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

Upsert operation in SOAPUI to change the Account Name in salesforce

How to create an upsert operation in SOAPUI inorder to change the Account name in salesforce.
Using the SOAPUI Tool I tried to write a connnection string like UPDATE table name SET column name WHERE column name = SOme value
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:urn="urn:enterprise.soap.sforce.com">
<soapenv:Header>
<urn:SessionHeader>
<urn:sessionId>00Do0000000K8o2!ARMAQPVLekBy0VKNXDIVHysA0Nn2FOAZKJBkixYVB6UnGgpz1oTSmAz2hwE41DhhB12Mf8Zi9wkKuDUHkLlXu84J7IsHrCLk</urn:sessionId>
</urn:SessionHeader>
</soapenv:Header>
<soapenv:Body>
<urn:query>
<urn:queryString>
UPDATE Account SET Name ='Maddi' where Id ='001o000000RIrLhAAL' </urn:queryString>
</urn:query>
</soapenv:Body>
</soapenv:Envelope>
Error is shown below
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:sf="urn:fault.enterprise.soap.sforce.com" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<soapenv:Body>
<soapenv:Fault>
<faultcode>sf:MALFORMED_QUERY</faultcode>
<faultstring>MALFORMED_QUERY: unexpected token: UPDATE</faultstring>
<detail>
<sf:MalformedQueryFault xsi:type="sf:MalformedQueryFault">
<sf:exceptionCode>MALFORMED_QUERY</sf:exceptionCode>
<sf:exceptionMessage>unexpected token: UPDATE</sf:exceptionMessage>
<sf:row>1</sf:row>
<sf:column>0</sf:column>
</sf:MalformedQueryFault>
</detail>
</soapenv:Fault>
</soapenv:Body>
</soapenv:Envelope>

Resources