Hello!
I am currently trying to generate the proper XML format for a specific "Any Type" element within my requests using Zeep.
The WSDL of this element is:
<xs:complexType name="Property">
<xs:attribute name="Name" type="xs:string" use="required"/>
<xs:sequence>
<xs:element minOccurs="0" name="Value" type="xs:anyType"/>
</xs:sequence>
</xs:complexType>
I have verified that the proper working format (in the case where the value is a string) for the resulting XML is something like:
<Property Name="details">
<Value xmlns:xs="http://www.w3.org/2001/XMLSchema" xsi:type="xs:string">Some Text</Value>
</Property>
I am however unable to ensure the xmlsn:xs and xsi:type attributes are present in the XML contents that Zeep generates.
With many attempts, the closest I've been able to get was:
<Property Name="details">
<Value>Some Text</Value>
</Property>
I've been playing around with AnyObject, ComplexType, AnyType and other elements of the Zeep library without success.
I am basically looking for pointers on how to properly add those two missing attributes to my Value element and how to properly add the "xsi" namespace to the SOAP envelope.
Zeep version: 0.18.1, installed via pip
Thank you.
Turns out that the anyType wasn't really supported well. I've just add a commit which allows you to do the following:
from zeep import xsd
value = xsd.AnyObject(xsd.String(), 'Some Text')
obj = Property(Value=value)
I've updated the docs for this, see http://docs.python-zeep.org/en/master/datastructures.html#anytype-objects.
Thanks for the detailed report btw, and let me know if you it still doesn't work
Hello again, thanks for the quick response!
After quickly trying it out with the new commit and your example format on my end, this is the result I'm getting:
<Property Name="details">
<Value xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xsd:string">Some Text</Value>
</Property>
The service I'm sending requests to accepts xsi:type="xs:string", whereas we now have xsi:type="xsd:string".
I am not quite sure if "xs" and "xsd" are equivalent at this position or if "xs" is the only correct one.
If it helps, this is the error I am receiving, which leads me to think that maybe it should be "xs"? :
Unmarshalling Error: prefix xsd is not bound to a namespace
So the xsd namespace is never defined? Do you have an example script for me which I can run?
All the calls to the service require credentials that I can't give out so I can't provide a working example script. But, the full wsdl is public and I can provide a subset of the code I use without the credentials bit and the XML generated by Zeep, if that helps.
wsdl address:
https://leprixdugros.progressionlive.com/server/ws/v1/ProgressionWebService?wsdl
http://leprixdugros.progressionlive.com/server/ws/v1/ProgressionWebService?wsdl=ProgressionPortType.wsdl
Code:
from zeep import Client
from zeep import xsd
from zeep.plugins import HistoryPlugin
from zeep.wsdl.utils import etree_to_string
from lxml import etree
history = HistoryPlugin()
wsdl = 'https://leprixdugros.progressionlive.com/server/ws/v1/ProgressionWebService?wsdl'
client = Client(wsdl, plugins=[history])
Credentials = client.get_type('ns12:Credentials')
credentials = Credentials(Username="SomeUsername", Password="SomePassword")
credentials = client.service.Login(credentials=credentials)
Task = client.get_type('ns2:Task')
RecordRef = client.get_type("ns11:RecordRef")
ArrayOfProperty = client.get_type("ns11:ArrayOfProperty")
Property = client.get_type("ns11:Property")
properties_list = []
prop = Property(Name="details", Value=xsd.AnyObject(xsd.String(), 'SomeText'))
properties_list.append(prop)
props = ArrayOfProperty(Property=properties_list)
task_record_ref = RecordRef(Type="TASK_TYPE", Label="COL", Id=0)
task = Task(
TypeRef=task_record_ref,
Properties=props
)
client.service.CreateTask(credentials=credentials, task=task, dispatch=False)
print(etree_to_string(history.last_sent["envelope"]))
Generated XML:
<?xml version='1.0' encoding='utf-8'?>
<soap-env:Envelope xmlns:ns11="http://base.v1.ws.progression.diffusion.cc" xmlns:ns2="http://task.v1.ws.progression.diffusion.cc" xmlns:ns6="http://message.v1.ws.progression.diffusion.cc" xmlns:soap-env="http://schemas.xmlsoap.org/soap/envelope/">
<soap-env:Body>
<ns6:CreateTaskRequest dispatch="false">
<ns6:credentials Password="SomePassword" SessionID="SomeSessionID" Username="SomeUsername"/>
<ns6:task>
<ns11:Properties>
<ns11:Property Name="details">
<ns11:Value xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xsd:string">SomeText</ns11:Value>
</ns11:Property>
</ns11:Properties>
<ns2:TypeRef Id="0" Label="COL" Type="TASK_TYPE" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="ns11:RecordRef"/>
<ns2:HumanResourceRef/>
<ns2:ClientRef/>
<ns2:NodeRef/>
</ns6:task>
</ns6:CreateTaskRequest>
</soap-env:Body>
</soap-env:Envelope>
Error message:
Unmarshalling Error: prefix xsd is not bound to a namespace
I believe they may be using Java on their end but I don't know their setup. ProgressionLive's free trial doesn't appear to be freely available without applying for one on their site so it doesn't look like you could execute scripts with them on your end, unfortunately.
As you can see in the XML though, the "xsd" part appears only within the Value element the way I copied it earlier and it doesn't seem to be recognized on the other end, whereas "xs" is.
The generated XML is not valid. The xsd shorthand is never declared. I'll fix it asap :-)
Just came across the exact same issue (xsd namespace undeclared when serialising AnyObject). I can help test this ..
Just came back to say that, until there's a clean fix for this, we are using a dirty temporary patch to work around the issue in a commit I've made here.
In case this can help anyone else experiencing this:
https://github.com/resulto-admin/python-zeep/commit/d6d3b778428eec23d3cfac8193a5bfefb55277cd
This requires the commit by @mvantellingen mentionned earlier in this issue (present in zeep 0.20)
So this last issue seems to be a bug in lxml when using cleanup_namespaces()
Example
from lxml import etree
root = etree.Element('root')
node = etree.SubElement(root, 'node')
node.set(
etree.QName('http://www.w3.org/2001/XMLSchema-instance', 'type'),
etree.QName('http://www.w3.org/2001/XMLSchema', 'string'))
print(etree.tostring(root, pretty_print=True).decode('utf-8'))
etree.cleanup_namespaces(root)
print(etree.tostring(root, pretty_print=True).decode('utf-8'))
I'll see if I am able to fix this in lxml
So i've decided to remove the usage of etree.cleanup_namespaces with some other changes. It should work now!
Let me know
Hi @mvantellingen
After testing on your most recent commit, everything related to this seems to be working great now, at least on my end.
Awesome! Thank you.
Hi @mvantellingen
I've run your latest commit with my application source code, XML payload looks fine now - great job, many thanks
Thanks for the feedback!
Hi, I'm facing issue "XML element or attribute is missing" after making connection using wsse in Zeep package. Please see my code below and could you please suggest me some work around to resolve the issue:
from zeep import Client
from zeep.wsse.username import UsernameToken
import requests, base64, dicttoxml, csv
from datetime import datetime
filenetUrl = 'http://vmslcilgce05:9080/wsi/FNCEWS40MTOM/'
filenetWsdl = 'http://vmslcilgce05:9080/wsi/FNCEWS40SOAP/wsdl'
filenetUsername = 'username'
filenetPassword = 'password'
filenetObjectStoreName = "EDM"
filenetClassName = "EDMTask"
filenetPropertyName = "EDMName, EDMDescription, EDMTaskAction, EDMTaskType, EDMCaseSysID, EDMStatus, EDMNotifyEmail, EDMExecTime, EDMStartTime, EDMStopTime, EDMNumTotal, EDMNumSuccess, EDMNumFail";
client = Client(filenetUrl, wsse=UsernameToken(filenetUsername, filenetPassword))
print("=============== client Value ======================")
print(client.wsdl.dump())
print("=============== End printing client value ======================")
sql = ''' SELECT {propertyName} FROM {class} '''
sql = sql.replace('{propertyName}', filenetPropertyName)
sql = sql.replace('{class}', filenetClassName)
print("client call")
object_store_scope_type = client.get_type('ns0:ObjectStoreScope')
print("===============End client call====================")
object_store_scope = object_store_scope_type( objectStore = filenetObjectStoreName)
repository_search_type = client.get_type('ns0:RepositorySearch')
repository_search = repository_search_type( continuable = 1,
SearchScope = object_store_scope,
SearchSQL = sql,
maxElements= -1
)
print("repository serach type")
print(repository_search_type)
print("repository_search")
print(repository_search)
client.service.ExecuteSearch(repository_search) #I'm facing error at this line.
Output:
Repository search type:
{
'SelectionFilter': None,
'SearchScope': {
'_value_1': None,
'objectStore': 'EDM'
},
'SearchSQL': ' SELECT EDMName, EDMDescription, EDMTaskAction, EDMTaskType, EDMCaseSysID, EDMStatus, EDMNotifyEmail, EDMExecTime, EDMStartTime, EDMStopTime, EDMNumTotal, EDMNumSuccess, EDMNumFail FROM EDMTask ',
'maxElements': None,
'continueFrom': None,
'continuable': 1,
'repositorySearchMode': None
}
I used this link https://www.ibm.com/support/knowledgecenter/en/SSNW2F_5.2.0/com.ibm.p8.ce.dev.cews.doc/examples/repositorysearch_ex.htm
for creating the python script.