I need an output like this in Spyne:
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<soapenv:Body>
<getActiveServicesResponse xmlns="http://mci.tajmi.ir/">
<getActiveServicesReturn>12345:2030:hafez poem:hafez </getActiveServicesReturn>
<getActiveServicesReturn>12346:2031:شعر طنز:tanz </getActiveServicesReturn>
<getActiveServicesReturn>bardari123:203861:سرویس بارداري :bar
</getActiveServicesReturn>
</getActiveServicesResponse>
</soapenv:Body>
</soapenv:Envelope>
What I can generate is
<?xml version='1.0' encoding='UTF-8'?>
<soap11env:Envelope xmlns:soap11env="http://schemas.xmlsoap.org/soap/envelope/" xmlns:tns="http://mci.tajmi.ir/">
<soap11env:Body>
<tns:getActiveServicesResponse>
<tns:getActiveServicesReturn>
<tns:string>12345:2030:hafez poem:hafez</tns:string>
<tns:string>12346:2031:شعر طنز:tanz </tns:string>
....
</tns:getActiveServicesReturn>
</tns:getActiveServicesResponse>
</soap11env:Body>
</soap11env:Envelope>
How can I customize the output? I tried complex methods without success.
have a look at my code at https://github.com/timi-ro/simulator. you can find how to make it. Also read it:
Spyne - how to duplicate one elements of wsdl file created by spyne?
Related
I am new to python and I have an input xml which has a soap envelope embedded in it under a child node.
Input xml:
<SyncShipmentCreation xmlns="http://schema.infor.com/InforOAGIS/2" releaseID="2">
<ApplicationArea>
<CreationDateTime>2022-06-22T14:21:56Z</CreationDateTime>
</ApplicationArea>
<DataArea>
<Sync>
<TenantID>TLD_TST</TenantID>
</Sync>
<ShipmentCreation>
<soapenv:Envelope xmlns:dns="http://schema.infor.com/InforOAGIS/2" xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<soapenv:Header>
</soapenv:Header>
<soapenv:Body>
<ShipmentRequest xmlns="http://xxxyyyzzz.com/ShipmentMsgRequest">
...
</ShipmentRequest>
</soapenv:Body>
</soapenv:Envelope>
</ShipmentCreation>
</DataArea>
</SyncShipmentCreation>
The soap part is the Output needed. Like
<soapenv:Envelope xmlns:dns="http://schema.infor.com/InforOAGIS/2" xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
..............
</soapenv:Envelope>
Is this possible? I could not find how to parse/extract this value and assign to an output variable. Please help.
One of the ways of doing it is by using the lxml library in the following way:
from lxml import etree
soap ="""[your xml above]"""
doc1 = etree.XML(soap)
#locate your target nodes and assign them to a second document
doc2 = doc1.xpath('//*[local-name()="ShipmentCreation"]/*')[0]
print(etree.tostring(doc2).decode())
The output should be your expected output.
I am using Spyne with Django CMS.
A web service is calling my system and I want to reply with the below.
Can I use Spyne for customize response? Or do I have to go through models?
Please advise.
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<soapenv:Header/>
<soapenv:Body>
<tns:initTestQueryResponse xmlns:tns="http://test.com/interface/test/v2"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://test.com/interface/test/v2 testQuery.xsd"
xmlns:v21="http://test.com/model/generic-query/v2"
xmlns:v22="http://test.com/model/common/v2">
<tns:field key="ID" type="ID">
<v21:description lang="en">Identifier</v21:description>
</tns:field>
<tns:field key="CUSTOMER_NAME" type="TEXT">
<v21:description lang="en">Customer Name</v21:description>
<v21:layoutOptions bold="true" italic="false" direction="HORIZONTAL"/>
</tns:field>
<tns:section key="CUSTOMER">
<v21:description lang="en">Customer</v21:description>
</tns:section>
<tns:advancedQuery>
<tns:criteriaGroup key="CUSTOMER" operator="OR">
<v21:criterion key="ID" />
<v21:criterion key="CUSTOMER_NAME" />
</tns:criteriaGroup>
</tns:advancedQuery>
<tns:advanceQueryPerson>
<tns:criteriaGroup key="CUSTOMER" operator="OR">
<v21:criterion key="ID" />
<v21:criterion key="CUSTOMER_NAME" />
</tns:criteriaGroup>
</tns:advanceQueryPerson>
<tns:context>
<v22:status>OK</v22:status>
</tns:context>
</tns:initTestQueryResponse>
</soapenv:Body>
</soapenv:Envelope>
This the request
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<soapenv:Header/>
<soapenv:Body>
<p:initTestQueryRequest xmlns:p="http://test.com/interface/test/v2"
xmlns:p1="http://test.com/model/common/v2"
xmlns:p2="http://test.com/model/generic-query/v2"
xmlns:p3="http://test.com/model/test/v2"
xmlns:p4="http://test.com/model/service-fault/v2"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://test.com/interface/test/v2 ../service/test/v2/TestQuery.xsd "
xsi:type="anyType"/>
</soapenv:Body>
</soapenv:Envelope>
You have two options:
Use a bare method named initTestQuery whose return type should be a class named "initTestQueryResponse" whose namespace is "http://test.com/interface/test/v2". You need to return an initTestQueryResponse instance from the initTestQuery function.
Use a bare method named "initTestQuery" whose return type is AnyXml. You need to return an lxml.etree.Element() that contains the tags you need. Please consult the lxml documentation about how to do that.
If you want to "edit" requests after they are deserialized but before they are validated, you must subclass the protocol and override create_in_document.
class MyProtocol(Soap11):
def create_in_document(self, ctx, charset=None):
super(MyProt, self).create_in_document(ctx, charset=charset)
# Do whatever you want with ctx.in_document
app = Application(in_protocol=MyProtocol(...), ...)
I hope this helps.
I am making a request to the Salesforce merge API and getting a response like this:
xml_result = '<?xml version="1.0" encoding="UTF-8"?>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns="urn:partner.soap.sforce.com">
<soapenv:Header>
<LimitInfoHeader>
<limitInfo>
<current>62303</current>
<limit>2680000</limit><type>API REQUESTS</type></limitInfo>
</LimitInfoHeader>
</soapenv:Header>
<soapenv:Body>
<mergeResponse>
<result>
<errors>
<message>invalid record type</message>
<statusCode>INSUFFICIENT_ACCESS_ON_CROSS_REFERENCE_ENTITY</statusCode>
</errors>
<id>003skdjf494244</id>
<success>false</success>
</result>
</mergeResponse>
</soapenv:Body>
</soapenv:Envelope>'
I'd like to be able to parse this response and if success=false, return the errors, statusCode, and the message text.
I've tried the following:
import xml.etree.ElementTree as ET
tree = ET.fromstring(xml_result)
root.find('mergeResponse')
root.find('{urn:partner.soap.sforce.com}mergeResponse')
root.findtext('mergeResponse')
root.findall('{urn:partner.soap.sforce.com}mergeResponse')
...and a bunch of other variations of find, findtext and findall but I can't seem to get these to return any results. Here's where I get stuck. I've tried to follow the ElementTree docs, but I don't understand how to parse the tree for specific elements.
Element.find() finds the first child with a particular tag
https://docs.python.org/2/library/xml.etree.elementtree.html#finding-interesting-elements
Since mergeResponse is a descendant, not a child, you should use XPath-syntax in this case:
root.find('.//{urn:partner.soap.sforce.com}mergeResponse')
will return your node. .// searches all descendants starting with the current node (in this case the root).
I have the below XML document I am trying to parse. I just need to grab one node from the document. I need to get the serviceProfile text. I'm banging my head against the desk here... I am new to Python.
<?xml version='1.0' encoding='UTF-8'?>
<soapenv:Envelope
xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<soapenv:Body>
<ns:getUserResponse
xmlns:ns="http://www.cisco.com/AXL/API/11.5">
<return>
<user uuid="{blbhbl-bhblb-kbhb}">
<firstName>fname</firstName>
<displayName>fname lname</displayName>
<middleName/>
<lastName>lname</lastName>
<userid>wooty</userid>
<password/>
<pin/>
<mailid>wooty#woot.com</mailid>
<department/>
<manager/>
<userLocale />
<associatedDevices/>
<primaryExtension/>
<associatedPc/>
<enableCti>false</enableCti>
<digestCredentials/>
<phoneProfiles/>
<defaultProfile/>
<presenceGroupName uuid="{sdsds-sdsds-sdsdsd-sdsdsd-sdsd}">Standard Presence group</presenceGroupName>
<subscribeCallingSearchSpaceName/>
<enableMobility>false</enableMobility>
<enableMobileVoiceAccess>false</enableMobileVoiceAccess>
<maxDeskPickupWaitTime>10000</maxDeskPickupWaitTime>
<remoteDestinationLimit>4</remoteDestinationLimit>
<associatedRemoteDestinationProfiles/>
<associatedTodAccess/>
<status>1</status>
<enableEmcc>false</enableEmcc>
<associatedCapfProfiles/>
<ctiControlledDeviceProfiles/>
<patternPrecedence />
<numericUserId />
<mlppPassword />
<customUserFields/>
<homeCluster>true</homeCluster>
<imAndPresenceEnable>true</imAndPresenceEnable>
<serviceProfile uuid="{dsdsdsd-sdsdsd-sdsd-sdsds-sdsds}">1 IM Presence Only</serviceProfile>
<lineAppearanceAssociationForPresences/>
<directoryUri>blah#wooty.com</directoryUri>
<telephoneNumber>555-555-5555</telephoneNumber>
<title/>
<mobileNumber/>
<homeNumber/>
<pagerNumber/>
<extensionsInfo/>
<selfService />
<userProfile/>
<calendarPresence>false</calendarPresence>
<ldapDirectoryName uuid="{sdsd-sdsdsd-sdsds-sdsds}">someinfo</ldapDirectoryName>
<userIdentity>blah#woot.com</userIdentity>
<nameDialing>blehWoot</nameDialing>
<ipccExtension/>
<convertUserAccount uuid="{sdsd-sdsdsd-sdsds-sdsds}">someinfo</convertUserAccount>
<enableUserToHostConferenceNow>false</enableUserToHostConferenceNow>
<attendeesAccessCode/>
</user>
</return>
</ns:getUserResponse>
</soapenv:Body>
</soapenv:Envelope>
Based on #danielHaley suggestions i created the following code to retrieve the node.
#read XML response and get service profile
tree = ET.ElementTree(ET.fromstring(response.content))
root = tree.getroot()
serviceprofile = root.find(".//serviceProfile").text
Worked great. thank you so much for your help.
I am calling an API by sending an xml request by doing a string formatting like this:
data = '''<?xml version="1.0" encoding="utf-8"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<SOAP-ENV:Body>
<ns2:MultiAvailabilityRequest xmlns:m="http://www.derbysoft.com/doorway" Password="CoolJoe" Token="{token}" UserName="CoolJoe">
<ns2:MultiAvailabilityCriteria NumberOfUnits="{units}">
<ns2:StayDateRange CheckIn="2016-05-02" CheckOut="2016-05-04"/>
<ns2:GuestCounts>
<ns2:GuestCount AdultCount="{adultcount}"/>
</ns2:GuestCounts>
<ns2:HotelCodes>
<ns2:HotelCode>{hotelcode}</ns2:HotelCode>
</ns2:HotelCodes>
</ns2:MultiAvailabilityCriteria>
</ns2::MultiAvailabilityRequest>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>'''.format(token=token, units=units, adultcount=adultcount, hotelcode=hotelcode)
The above code is working fine and getting the value of different hotelcodes, token etc and showing the results based on them.
But, I have one more different requirement where the hotelcodes could be more than 1 (either 2,3 or more). And, the required xml will look like this:
data = '''<?xml version="1.0" encoding="utf-8"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<SOAP-ENV:Body>
<ns2:MultiAvailabilityRequest xmlns:m="http://www.derbysoft.com/doorway" Password="CoolJoe" Token="{token}" UserName="CoolJoe">
<ns2:MultiAvailabilityCriteria NumberOfUnits="{units}">
<ns2:StayDateRange CheckIn="2016-05-02" CheckOut="2016-05-04"/>
<ns2:GuestCounts>
<ns2:GuestCount AdultCount="{adultcount}"/>
</ns2:GuestCounts>
<ns2:HotelCodes>
<ns2:HotelCode>{hotelcode1}</ns2:HotelCode>
<ns2:HotelCode>{hotelcode2}</ns2:HotelCode>
<ns2:HotelCode>{hotelcode3}</ns2:HotelCode>
</ns2:HotelCodes>
</ns2:MultiAvailabilityCriteria>
</ns2::MultiAvailabilityRequest>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>'''.format(token=token, units=units, adultcount=adultcount)
So, my question is: how do I check whether two hotelcodes are present or more than two. As you can see from second xml for each hotel code, a new line like this adds up:
<ns2:HotelCode>{hotelcode1}</ns2:HotelCode>
Any help would be appreciated. Thanks.
Basically you should split the process in two parts:
fill in the hotel codes (doesn't really matter if it's one or more):
hotelcode_string =''.join(['<ns2:HotelCode>{hotelcode}</ns2:HotelCode>'.format(hotelcode=code) for code in set([item["hotelcode"] for item in hotelcode])])
put the hotel code section in the xml:
data = '''.... <ns2:HotelCodes>{hotelcode_string}</ns2:HotelCodes>
...'''.format(token=token, units=units, adultcount=adultcount,hotelcode_string=hotelcode_string)