I use DataSource generated from xsd schema. I need to get all fields from DataSource, also nested ones. My problem is the same like in this topic from Smartclient forum forum, when I use DataSource.getFields() its return only first level fields.
Does anyone know how can I get also nested fields?
I m not exactly sure if this will solve your issue. CompanySlaves is not references in any where in xsd. Type is defined but not used.
I think you need to have <xsd:element name="SomeElementName" type="tns:CompanySlaves"></xsd:element> in your xsd definition
<?xml version="1.0" encoding="UTF-8"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://xml.netbeans.org/schema/newXmlSchema"
xmlns:tns="http://xml.netbeans.org/schema/newXmlSchema"
elementFormDefault="qualified">
<xsd:element name="SubrogationClaim" type="tns:SubrogationClame"></xsd:element>
<xsd:complexType name="SubrogationClame">
<xsd:sequence>
<xsd:element name="CompanyName" type="xsd:string"></xsd:element>
<xsd:element name="CompanyPlace" type="xsd:string"></xsd:element>
<xsd:element name="CompanyEmploee" type="tns:SubrogationClame"></xsd:element>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="CompanySlaves">
<xsd:sequence>
<xsd:element name="EmploeeName" type="xsd:string"></xsd:element>
<xsd:element name="EmploeeSalary" type="xsd:string"></xsd:element>
</xsd:sequence>
</xsd:ComplexType>
</xsd:schema>
I found solution. To get nested fields it’s possible to use DataSource.getDataSource(ID). For example, if dataSource is main DataSource, it can be done like that:
private List<DataSourceField> getAllFields(DataSource dataSource)
{
List <DataSourceField> fieldList = new ArrayList<DataSourceField>();
DataSourceField [] fields = dataSource.getFields();
fieldList.addAll(Arrays.asList(fields));
for (DataSourceField field : fields);
{
String fieldName = field.getName();
DataSource ds = DataSource.getDataSource(fieldName);
if (ds != null)
{
fieldList.remove(field);
DataSourceField[] nFields = ds.getFields();
fieldList.addAll(Arrays.asList(nFields));
getAllFields(ds);
}
}
return fieldList;
}
Related
I'm connecting to a SOAP v2 webservice with Python3.7 and zeep. One call to create an object requires a complex structure to be passed as an argument. This is the WSDL for the call and it's arguments:
<message name="catalogProductAttributeAddOptionRequest">
<part name="sessionId" type="xsd:string"/>
<part name="attribute" type="xsd:string"/>
<part name="data" type="typens:catalogProductAttributeOptionEntityToAdd"/>
</message>
<complexType name="catalogProductAttributeOptionEntityToAdd">
<all>
<element name="label" type="typens:catalogProductAttributeOptionLabelArray"/>
<element name="order" type="xsd:int"/>
<element name="is_default" type="xsd:int"/>
</all>
</complexType>
<complexType name="catalogProductAttributeOptionLabelArray">
<complexContent>
<restriction base="soapenc:Array">
<attribute ref="soapenc:arrayType" wsdl:arrayType="typens:catalogProductAttributeOptionLabelEntity[]"/>
</restriction>
</complexContent>
</complexType>
<complexType name="catalogProductAttributeOptionLabelEntity">
<all>
<element name="store_id" type="typens:ArrayOfString"/>
<element name="value" type="xsd:string"/>
</all>
</complexType>
The problem that I have is how to pass the "data" argument to the function in Python 3 using zeep. I have an example on how to do this in php:
$label = array (
array(
"store_id" => array("0"),
"value" => "some random data"
)
);
$data = array(
"label" => $label,
"order" => "10",
"is_default" => "1"
);
$orders = $client->catalogProductAttributeAddOption($session, $attributeCode, $data);
This code is supossed to work altough I haven't tested it. So, the $data structure should have the equivalent in a python dict as this one:
data=[
{
"label": [
[
{
"store_id":["0"],
"value":"some random data"
}
]
],
"order":10,
"is_default":1
}
]
And I call the function this way:
client.service.catalogProductAttributeAddOption(sessionId=sessionid,attribute="manufacturer",data=data)
If I do that I receive this exception:
TypeError: Any element received object of type 'list', expected lxml.etree._Element or builtins.dict or zeep.objects.catalogProductAttributeOptionLabelEntity
See http://docs.python-zeep.org/en/master/datastructures.html#any-objects for more information
So I start investigating about the Any elements and I discover a way of casting parts of the structure to its type in the wsdl namespace, so I do this:
entity={
"store_id":["0"],
"value":"some random data"
}
catalogProductAttributeOptionLabelEntity=client.get_type('ns0:catalogProductAttributeOptionLabelEntity')
retyped_entity=catalogProductAttributeOptionLabelEntity(entity)
label=[
retyped_entity
]
catalogProductAttributeOptionLabelArray = client.get_type('ns0:catalogProductAttributeOptionLabelArray')
retyped_label=catalogProductAttributeOptionLabelArray(label)
data=[
{
"label": retyped_label,
"order":10,
"is_default":1
}
]
catalogProductAttributeOptionEntityToAdd=client.get_type('ns0:catalogProductAttributeOptionEntityToAdd')
retyped_data=catalogProductAttributeOptionEntityToAdd(data)
client.service.catalogProductAttributeAddOption(sessionId=sessionid,attribute="manufacturer",data=retyped_data)
And then, I got this error:
ValidationError: 'Missing element for Any'
I've investigated and it seems that this error comes when the structure is not in the format that is required... I mean, like if the dict I wrote before were not equivalent to the php structure written before, and if the new structure created with castings to the required types were not in the structure required.
At this point I'm stucked and I don't know how to go on. Any expert eye can see where is my error?
By the way, if this is solved, this also answer the question "How to write a manufacturer in Magento 1 using SOAP v2 webservice with Python and Zeep". Question which is not solved anywhere.
Thanks in advance.
I've been able to execute the function by using this structure:
ArrayOfString=client.get_type('ns0:ArrayOfString')
data=[
{
"label":[{
"store_id":ArrayOfString(["0"]),
"value":"some random data"
}],
"order":"10",
"is_default":"1"
}
]
client.service.catalogProductAttributeAddOption(sessionId=sessionid,attribute="manufacturer",data=data)
I choosed a general title because my question was about trying to find out how to convert the wsdl structure needed by the function into a python dict, but this question solves a very particular question which is more interesting, and that is: "How to write a manufacturer in the magento soap V2 webservice using Python 3 and zeep".
I have a JAXB-annotiated class with some required fields:
...
#XmlElement(required = true, nillable = false)
private String credentials = null;
...
Using SoapUI, the generated wsdl is like this:
...
<xs:element name="credentials" type="xs:string"/>
...
Is there any way to get the required-information into the wsdl? If I understood this right, than the wsdl should look like this (maybe that):
...
<xs:element wsdl:required="true" name="credentials" type="xs:string"/>
...
#XmlElement(required=true) corresponds to an element in the XML Schema with the attribute minOccurs="1". Since this the default it is not required to be specified.
I have an exception:
public class MyException extends Exception {
public MyException() {
}
public MyException(String message) {
super(message);
}
}
The exception is thrown from a webservice method.
When I generate the Webservice using a regular Jax-ws implementation, the WSDL has:
<xs:complexType name='MyException'>
<xs:sequence>
<xs:element minOccurs='0' name='message' type='xs:string' />
</xs:sequence>
</xs:complexType>
But, when generating the webservice with cxf, I get:
<xs:complexType name='MyException'> <xs:sequence/></xs:complexType>
Which is not ok for me: I expect to get the first variant.
Can you please advise how to force CXF to provide the desired result?
Remark: I cannot alter the code in the exception! The Exception does not have any fields!
Thanks!
This is already reported and fixed in the latest CXF versions:
https://issues.apache.org/jira/browse/CXF-4748
Getting following error while unmarshalling a response String(in xml format). Initially it was complaining about the and ,so I removed the soap part from the response.Now it comes up with this error.
Classes are created from provided WSDL using JAXB 2
**javax.xml.bind.UnmarshalException: unexpected element (uri:"http://ws.taxwareenterprise.com", local:"calculateDocumentResponse"). Expected elements are (none)
at com.sun.xml.bind.v2.runtime.unmarshaller.UnmarshallingContext.handleEvent(UnmarshallingContext.java:662)
at com.sun.xml.bind.v2.runtime.unmarshaller.Loader.reportError(Loader.java:258)
at com.sun.xml.bind.v2.runtime.unmarshaller.Loader.reportError(Loader.java:253)**
Here is my response string (part of it)
**<calculateDocumentResponse xmlns="http://ws.taxwareenterprise.com">
<txDocRslt>
<jurSumRslts>
<jurSumRslt>
<xmptAmt>5.0</xmptAmt>
<txableAmt>15.0</txableAmt>
<txAmt>0.04</txAmt>
<txJurUID>...**
Here goes my xsd for "CalculationResponse"(part of it)
<xs:complexType name="CalculationResponse">
<xs:sequence>
<xs:element name="txDocRslt" type="tns:TxDocRslt"/>
</xs:sequence>
</xs:complexType>
and this is my code for unmarshalling:
**final JAXBContext context = JAXBContext.newInstance(CalculationResponse.class);
final Unmarshaller unmarshaller = context.createUnmarshaller();
response = processResponse(response);//for removing soap headers
responseObj = (CalculationResponse) unmarshaller.unmarshal(new StringReader(response));//Fails here...
final TxDocRslt txDocRslt = responseObj.getTxDocRslt();**
I'm currently using Zend_Soap_AutoDiscover to generate my WSDL file, the problem is I want this wsdl to handle output of type ArrayOfString ( string[] ). so I changed the complex type strategy to Zend_Soap_Wsdl_Strategy_ArrayOfTypeSequence, it works properly but the problem is that the output isn't really an array of string the output xml is somthing like this :
<xsd:complexType name="ArrayOfString">
<xsd:sequence>
<xsd:element name="item" type="xsd:string" minOccurs="0" maxOccurs="unbounded"/>
</xsd:sequence>
</xsd:complexType>
But I want output like this :
<xsd:complexType name="ArrayOfstring">
<xsd:complexContent>
<xsd:restriction base="soapenc:Array">
<xsd:attribute ref="soapenc:arrayType" wsdl:arrayType="xsd:string[]"/>
</xsd:restriction>
</xsd:complexContent>
</xsd:complexType>
so ,I used the new strategy , Zend_Soap_Wsdl_Strategy_ArrayOfTypeComplex, but the problem is that this strategy does not handle string[].
Finally -> What should I do :D?!
Try creating a response class that has just one attribute, as follows:
class Response
{
/** #var string[] */
public $items;
}
Then define your service class to return an object of type Response, as follows:
class Service
{
/**
* #param string
* #return Response
*/
public function process( $input )
{
$response = new Response();
// Populate $response->items[] object with strings...
return $response;
}
}
Then use the 'Zend_Soap_Wsdl_Strategy_ArrayOfTypeComplex' strategy when using Zend_Soap_Autodiscover to create the WSDL. Although this probably won't produce precisely the output you're after, it should produce something that is semantically closer than what you're currently getting. The key with this approach is to get the PHPDoc right.
If that still doesn't work, post the key bits of your code, as that will help resolve the issue more quickly.