4.9 Schema Rules
XML Scheme Definition (XSD) is a very powerful and versatile schema definition language. It would be difficult for service consumers to make sense of XSD schemas if SData allowed all possible variations on XSD. To avoid this, SData imposes a set of rules on schemas.
Here is a summary of the structural rules that SData imposes on schemas:
- Every resource kind MUST be defined by an <xs:element> directly under the root <xs:schema> element. The name attribute SHOULD be singular and in camel case (product, contact, salesOrder, …).
- Every resource kind definition element MUST be followed by a <xs:complexType> element. The name of the complex type MUST BE obtained by appending the –type suffix to the name of the resource kind. The resource kind definition and the complex type definition are linked together through the type attribute of the resource kind definition element.
The structure itself MUST be described as an <xs:all> list of property definition elements below the <xs:complexType> element.
- If the structure contains substructures, the substructures MUST be described as separate <xs:complexType> nodes under the root <xs:schema> node, and they MUST be referred to by means of a type attribute. The same complex type can be reused in several substructures.
- If a structure is used to form lists, the schema MUST contain a definition for its list type. The name of the list type MUST be obtained by adding a –list suffix to the structure name. The list type MUST be defined as an <xs:sequence>, as order is usually meaningful in a list.
- If a type is a basic type with restrictions (an enumeration, an integer with a range, a string with a maximum length), it SHOULD be described as a separate <xs:simpleType> node under the root <xs:schema> node and it SHOULD be refered to by means of a type attribute. If the basic type is an enumeration, its name SHOULD have the –enum suffix.
The general idea behind these rules is to impose a flat structure in which all the types, including substructures and simple types, are defined directly under the <xs:schema> root node, and referred to by their name.
XSD provides mechanisms to express various types of constraints. Uniqueness constraints, such as the <unique> element. Also cardinality constraints (minOccurs, maxOccurs), length and range restrictions, etc.
These constraints are binding for service consumers, they are not hints. If they are specified in the schema, the consumer becomes responsible for ensuring that the payloads that it sends to the producer conform to these constraints. From the provider’s side, exposing too many constraints goes somewhat against the first clause of Postel’s adage: “Be liberal in what you accept, and conservative in what you send”. On the other hand, it seems reasonable to impose that consumers be “reasonably conservative” in what they send, and that simple constraints like length and range restrictions be validated on the consumer side.
Cardinality constraints are somewhat problematic and should be introduced with care:
- The maxOccurs constraint is not very useful because resource types are defined with <xs:all>, which implies maxOccurs=”1”.
</tt>Note: This does not prevent the representation of one to many relationships because there is an intermediate element with cardinality 1, see the <orderLines> element in our feed example. * The minOccurs constraint SHOULD be set to 0 on all properties, even if they are mandatory. This is because consumers should be allowed to send partial payloads when updating resources. These partial payloads contain all properties that have been modified but are not required to contain all properties that are mandatory at creation time. The sme:isMandatory attribute SHOULD be used instead of minOccurs to flag properties that are mandatory at creation time.
The XML payloads embedded in SData feeds or entries MUST conform to the contract schema - in both directions and in HTTP responses as well as in POSTed payloads.
Validation introduces overhead. It can be turned off in production mode, assuming the provider is robust enough to handle invalid input. However, it SHOULD be turned on during development, at least on the provider side.
Schemas MAY be localized, like any other resource exposed by an SData provider. In a localized schema, the sme:label values are returned in the requested language.
The consumer controls schema localization through the HTTP Accept-Language header and the language query parameter. See localization section for details.
Schemas SHOULD carry a version number. If present, the version number MUST be placed in the version attribute of the top level <xs:schema> element and it MUST have the following structure: major.minor.revision where major, minor and revision are three integers that satisfy the following compatibility rules:
- Schemas with the same namespace different major version numbers MAY be incompatible with each other.
- A schema SHOULD be compatible with any schema having the same namespace, the same major version number and a lower minor version number.
- A schema MUST be compatible with any schema having the same namespace, the same major and minor version numbers and a lower revision number.
By “compatible”, we mean that a consumer which was validated against the older schema should function correctly with the newer schema.
SData consumers MUST comply with the above rules