We have an xsd schema that outlines all the possible data elements in our system, some are simple type elements and some are complex types. We gave this schema to another developer who will try to write up a web service using SOAP. The xsd in a dumb down sample looks like this.
<xs:element name="Element1"> .... </xs:element>
<xs:element name="Element2"> .... </xs:element>
<xs:element name="Element3"> .... </xs:element>
<xs:element name="Element4"> .... </xs:element>
I plan to send our data to him by calling his WebService method. Due to the type of message generated from my system, I will have two type of messages. The first one contains Element1 and Element4 only while the second type may contains Element3, Element4 and Element1. So what are the choice does he have here?
Does he have to create two separate web services and I'll consume them accordingly?
Create one web service and I'll consume that one web service for both of my message types.
In the second opotion, does it generate any schema validation error? if so is there a way to get around it? can I send him a custom SOAP header to indicates the message type I send so he can validates it against specific xsd elements?
I'm relatively new to WebService so if I misunderstood the the basic mechanism of SOAP, XSD and WebService please feel free to point them out or correct any of my above assumptions.
I think that he could make just one webservice.
I'm not very aquainted to XSD as well, but as far as I know, there is a minOccurs property that would make this work with just one webservice. For instance:
<!--The syntax may be incorrect-->
<xsd:complexType name="yourtype">
<xsd:sequence>
<xsd:element name="Element1" minOccurs="1" maxOccurs="1" .../>
<xsd:element name="Element2" minOccurs="0" maxOccurs="1" ..../>
<xsd:element name="Element3" minOccurs="1" maxOccurs="1" ..../>
<xsd:element name="Element4" minOccurs="1" maxOccurs="1" ..../>
</xsd:sequence>
</xsd:complexType>
Look at the minOccurs="0", it means that the Element2 can be ommited by the other programmer. If you want some element to repeat 0 or N times, you can put maxOccurs="unbounded".
Related
I am generating a c# class file from an XSD provided to me. I am able to do this without problems if using just the original native XSD. However, I would like to make modifications to the XSD by adding my own namespace and I would like to feed the newly modified XSD through the generator to produce a class file that contains class definitions I was provided, as well as definitions I have added.
So my understanding is that I need to add a namespace as well as the new attribute under that namespace. I do have access and the ability to modify the original XSD or add my own xsd.
I looked at this post which was similar Extend XSD with custom attributes?
An example of my attempt is below. In my attempt I am trying to add an attribute "Humidity" to the DeviceInfo element under the namespace of "mns". This currently shows an error of the "'mns:attribute' element is not supported in this context."
test.xsd
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://MyNamespace.com"
elementFormDefault="qualified" attributeFormDefault="unqualified">
<xs:element name="DeviceInfo">
<xs:complexType>
<xs:attribute name="Humidity" type="xs:float" />
</xs:complexType>
</xs:element>
</xs:schema>
main.xsd
<xs:schema targetNamespace="http://www.CIP4.org/JDFSchema_2_0"
xmlns="http://www.CIP4.org/JDFSchema_2_0"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:xsi ="http://www.w3.org/2001/XMLSchema-instance"
xmlns:mns="http://MyNamespace.com"
xsi:schemaLocation="http://MyNamespace.com ./test.xsd"
elementFormDefault="qualified"
attributeFormDefault="unqualified">
<xs:element name="DeviceInfo">
<xs:complexType>
<xs:sequence>
<xs:element maxOccurs="unbounded" minOccurs="0" ref="Activity"/>
<xs:element maxOccurs="2" minOccurs="0" ref="FileSpec"/>
<xs:element maxOccurs="unbounded" minOccurs="0" ref="JobPhase"/>
</xs:sequence>
<xs:attribute name="CounterUnit" type="NMTOKEN" use="optional"/>
<mns:Humidity value="0"/>
</xs:schema>
Currently this returns the 'mns:humidity' element is not supported in this context.
Can anybody explain how I can insert this to the complex type?
I also tried placing the mns:Humidity in the same tag as deviceInfo
<xs:element name="DeviceInfo mns:Humidity="0">
Sending that through the class generator produced two separate instances of "DeviceInfo" where the second had appended a 1.
How can I insert it in the complexType with the namespace?
In main.xsd, in the declaration of DeviceInfo, add
<xs:attribute ref="mns:Humidity"/>
plus a namespace declaration for "mns" and an xs:import declaration for that namespace with schemaLocation="test.xsd".
In test.xsd include the single declaration
<xs:attribute name="Humidity" type="xs:float"/>
Your attempt to solve this suggests that you are using trial and error rather than actually reading up what constructs in XSD actually mean. That isn't a good way forward. You seem fairly confused about the concepts, for example a schema should never contain an xsi:schemaLocation attribute.
I'm currently trying to add this XSD as a Service Reference to My ASP .Net MVC 4 project (http://voip.letscall.pt/PortalWebAPI/metadata?xsd=1). The problem is that whether I'm doing something wrong or the file has some kind of problem.
When I try to use the XSD.exe to parse the XSD, it gives me this error
Undefined complexType
'http://schemas.datacontract.org/2004/07/VS.PortalWebAPI:SupportTypes:Paging'
is used as a base for complex type extension.
The Paging SupportType is used on complexTypes, such as
<xs:complexType name="GetPbxCompanyContacts">
<xs:complexContent mixed="false">
<xs:extension xmlns:q13="http://schemas.datacontract.org/2004/07/VS.PortalWebAPI.API.SupportTypes" base="q13:Paging">
<xs:sequence>
<xs:element minOccurs="0" name="BranchId" type="xs:int" />
<xs:element minOccurs="0" name="Login" nillable="true" type="xs:string" />
</xs:sequence>
</xs:extension>
</xs:complexContent>
</xs:complexType>
<xs:element name="GetPbxCompanyContacts" nillable="true" type="tns:GetPbxCompanyContacts" />
The PortalWebAPI has 5 files:
XSDS
Service Types (voip.letscall.pt/PortalWebAPI/metadata?xsd=1)
Wcf Data Types (voip.letscall.pt/PortalWebAPI/metadata?xsd=0)
Wcf Collection Types (voip.letscall.pt/PortalWebAPI/metadata?xsd=2)
WSDLS
soap11 (voip.letscall.pt/PortalWebAPI/soap11)
soap12 (voip.letscall.pt/PortalWebAPI/soap12)
However, I've still not managed to find how to use it. Do I need only one, or do I need to import all?
I've also tried to add it straight to the project, through References -> Add Service Reference, only one or all of them, but no luck.
There should be a complexType named Paging in the XML schema document which has the target namespace mapped to the q13 prefix. Look for the document with:
targetNamespace="http://schemas.datacontract.org/2004/07/VS.PortalWebAPI.API.SupportTypes"
It should contain the Paging type.
You also should have an xs:import statement:
<xs:import namespace="http://schemas.datacontract.org/2004/07/VS.PortalWebAPI.API.SupportTypes"
schemaLocation="/path/to/your-schema.xsd"/>
If the Paging type is not declared in that namespace, or if you don't import the schema, it will not be found when you try to use it in your extension.
I use Apache CXF with Aegis data binding to provide a Java web service to a C# client. This works in principle very well. On the C# side, I would like to use the more limited DataContractSerializer, because it allows for collections instead of arrays. I understand using the DataContractSerializer limits the complexity of the Aegis-generated WSDL. Now I have a Java type that uses inheritance. Aegis is able to generate a WSDL that contains both the base and the derived type, but the DataContractSerializer does not seem to be able to understand this WSDL. SvcUtil falls back to the XmlSerializer, and my collections get ugly arrays.
I can imagine thee theoretical possibilities to deal with this issue:
Turn off Inheritance support with Aegis. This should cause the WSDL to contain only the derived types, containing each all of the base type properties.
Somehow make DataContractSerializer understand WSDL inheritance
Somehow make XmlSerializer use collections instead of arrays
I think the last two options are not possible, so I am stuck with the first one. How can I turn off Aegis inheritance?
Example WSDL fragment:
<xsd:schema attributeFormDefault="qualified" elementFormDefault="qualified" targetNamespace="http://tables.basic.meona.de">
<xsd:complexType abstract="true" name="BaseTreeNode">
<xsd:sequence>
<xsd:element minOccurs="0" name="active" type="xsd:boolean"/>
<xsd:element minOccurs="0" name="category" type="xsd:boolean"/>
<xsd:element minOccurs="0" name="name" nillable="true" type="xsd:string"/>
<xsd:element minOccurs="0" name="sequenceNumber" nillable="true" type="xsd:string"/>
</xsd:sequence>
</xsd:complexType>
</xsd:schema>
<xsd:complexType name="EmergencyDiagnosis">
<xsd:complexContent>
<xsd:extension base="ns0:BaseTreeNode">
<xsd:sequence>
<xsd:element minOccurs="0" name="externalCode" nillable="true" type="xsd:string"/>
<xsd:element minOccurs="0" name="favoriteDiagnosis" type="xsd:boolean"/>
<xsd:element minOccurs="0" name="identifier" nillable="true" type="xsd:string"/>
</xsd:sequence>
</xsd:extension>
</xsd:complexContent>
</xsd:complexType>
It seems former versions of Aegis did not generate the extension, so I am hoping it can be switched off: https://issues.apache.org/jira/browse/CXF-5176
After reading the Aegis source code, I helped myself with the following hack:
public class AegisNonExtensionBeanType extends BeanType {
#Override
public BeanTypeInfo getTypeInfo() {
BeanTypeInfo bti = super.getTypeInfo();
bti.setExtension(false);
bti.setExtensibleAttributes(false);
bti.setExtensibleElements(false);
return bti;
}
#Override
public AegisType getSuperType() {
return null;
}
}
If I register this AegisType for my inherited beans, it works.
Mustn't there be a better way?
I'm trying to use Spyne to provide web services from Python. I have everything working for a test function called SayHello(name, times). However, I'm wondering why Spyne wraps the name and times arguments in a complexType called SayHello? This makes consuming the web service in .NET much more cludgey (i.e. instead of appClient.SayHello("Dave", 5) I have to do SayHello args = new SayHello(); args.name = "Dave"; args.times = "5"; appClient.SayHello(args); which is very inelegant).
Is there a way to force Spyne not to wrap arguments in a complexType?
Here's the relevant portion of the current wsdl that Spyne generates:
<xs:schema targetNamespace="solutions.sfcs" elementFormDefault="qualified">
<xs:complexType name="SayHello">
<xs:sequence>
<xs:element name="name" type="xs:string" minOccurs="0" nillable="true"/>
<xs:element name="times" type="xs:integer" minOccurs="0" nillable="true"/>
</xs:sequence>
</xs:complexType>
You can pass _body_style='bare' to the #rpc decorator to prevent that wrapping. But you'll most likely get:
Exception: body_style='bare' can handle at most one function argument.
If you can fix this in a way that doesn't break other tests, I can merge your patch.
OK, obviously I'm doing something wrong here. I'm trying to create a webservice and I want "dateShipped" to be optional which means in the WSDL, I want minOccurs="0"
[Serializable]
[XmlType]
public class CTShipment
{
[XmlElement(Order = 0, IsNullable=false)] public CTDeliveryMethod DeliveryMethod;
[XmlElement(Order = 1, IsNullable=false)] public CTShipmentAddress ShipmentAddress;
[XmlIgnore] public bool dateShippedSpecified;
[XmlElement(Order = 2, IsNullable=false)] public DateTime dateShipped;
}
I want the WSDL to be generated like this:
<xs:complexType name="CTShipment">
<xs:annotation>
<xs:documentation>All details for the shipment of a suborder.</xs:documentation>
</xs:annotation>
<xs:sequence>
<xs:element name="DeliveryMethod" type="CTDeliveryMethod" nillable="false"/>
<xs:element name="ShipmentAddress" type="CTShipmentAddress" nillable="false"/>
<xs:element name="dateShipped" type="xs:dateTime" nillable="false" minOccurs="0"/>
</xs:sequence>
</xs:complexType>
Instead what I am actually getting is this:
<xs:complexType name="CTShipment">
<xs:sequence>
<xs:element name="DeliveryMethod" nillable="true" type="tns:CTDeliveryMethod"/>
<xs:element name="ShipmentAddress" nillable="true" type="tns:CTShipmentAddress"/>
<xs:element name="dateShipped" type="xs:dateTime"/>
<xs:element name="dateShippedSpecified" type="xs:boolean"/>
</xs:sequence>
</xs:complexType>
According to several things I've read (including http://msdn.microsoft.com/en-us/library/zds0b35c%28v=vs.90%29.aspx) including the public bool "dateShippedSpecified" should make "dateShipped" optional (minOccurs=0). As you can see, not only is this not happening but "dateShippedSpecified" is showing up in the WSDL even though it is marked with "[XmlIgnore]". You may have noticed that there is another problem as well: even though I'm specifying "IsNullable=false", I still get nillable="true" in the WSDL.
That is no less than 4 problems I can't explain all related to the same thing:
How can I set minOccurs to 0 in my WSDL?
Why isn't the [fieldName]Specified pattern making [fieldName] optional (minOccurs = 0)?
Even if it wasn't following the ___Specified pattern, why would dateShippedSpecified show up in the WSDL if it is marked with XmlIgnore?
Why is everything marked as nillable="true" even though I'm specifying "IsNullable=false"?
and as a bonus question, if anyone knows...
How do I get the annotation (as shown below) to be included?
<xs:annotation>
<xs:documentation>All details for the shipment of a suborder.</xs:documentation>
</xs:annotation>
This is due to Sequence element. It specifies that every element has minOccurs= 1.
And the WSDL uses a Sequence-Element instead of "All" because you specified an Order to them.
This requires that every value is present.
So it should work allready when you remove the Order. If you really need the order, than there is no way for you to leave out that value.
This is a bug in .net implementation.
According to W3C specs (for wsdl) minOccurs="0" can be used within sequence. "< sequence >"
means elements in order occurring 0 or more times.
For example look at official W3C definition of wsdl: http://www.w3.org/TR/wsdl
You will see elements like:
<sequence>
<element ref="wsdl:documentation" minOccurs="0"/>
</sequence>
For now when need to be .Net compatible use nillable="true"
which will give you DateTime? (nullable version) instead of DateTime.