How to constrain set of attributes in xsd - xsd

All
Please suggest me how to restrict in xsd schema the following:
<root>
<node action="action1" parameter="1" />
</root>
I need to require attribute "parameter" only if attribute "action" is defined.
Thanks,

W3C Schema doesn't have the ability to express conditionally required attributes.
Schematron is a great tool for validating that documents adhere to custom validation scenarios in which content is conditionally required.
You could define those attributes as optional in your schema, and then use Schematron to validate it against those conditional rules.

I created this xsd to attempt to solve the problem.
<?xml version="1.0" encoding="utf-8"?>
<xs:schema id="XMLSchema1"
targetNamespace="http://tempuri.org/XMLSchema1.xsd"
elementFormDefault="qualified"
xmlns="http://tempuri.org/XMLSchema1.xsd"
xmlns:mstns="http://tempuri.org/XMLSchema1.xsd"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
>
<xs:group name="populated">
<xs:sequence >
<xs:element name="node">
<xs:complexType>
<xs:attributeGroup ref="actionattrib" />
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:group>
<xs:group name="unpopulated">
<xs:sequence >
<xs:element name="node">
<xs:complexType>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:group>
<xs:attributeGroup name ="actionattrib">
<xs:attribute name="action1" type="xs:string" />
<xs:attribute name="parameter" type="xs:int" />
</xs:attributeGroup>
<xs:element name="root">
<xs:complexType>
<xs:choice minOccurs ="0">
<xs:group ref="populated" />
<xs:group ref ="unpopulated" />
</xs:choice>
</xs:complexType>
</xs:element>
</xs:schema>
And a test method:
public static void Go()
{
string nameSpace = "http://tempuri.org/XMLSchema1.xsd";
XmlSchemaSet schemas = new XmlSchemaSet();
schemas.Add(nameSpace, "XMLSchema1.xsd");
XDocument myDoc1 = new XDocument(
new XElement(XName.Get("root", nameSpace),
new XElement( XName.Get("node", nameSpace ))
)
);
myDoc1.Validate(schemas, (o, e) => { Console.WriteLine(e.Message); });
}
And finally got this exception when validating:
Multiple definition of element 'http://tempuri.org/XMLSchema1.xsd:node' causes the content model to become ambiguous. A content model must be formed such that during validation of an element information item sequence, the particle contained directly, indirectly or implicitly therein with which to attempt to validate each item in the sequence in turn can be uniquely determined without examining the content or attributes of that item, and without any information about the items in the remainder of the sequence.
Which matches Mads result. His answer should be accepted.

Related

specifying a JAXB external binding for XSD sequence nodeName and choice/sequence nodeName

I'm trying to eliminate "Element "___" shows up in more than one properties" with jxb external bindings on a xsd I don't maintain.
I can modify the XSD with the following that works:
<xs:complexType name="credit">
<xs:sequence>
<xs:element .../>
<xs:element name="link" type="link" minOccurs="0" maxOccurs="unbounded">
<xs:annotation> <xs:appinfo> <jxb:property name="linkElement"/> </xs:appinfo> </xs:annotation>
</xs:element>
<xs:choice>
<xs:sequence>
...
<xs:sequence minOccurs="0" maxOccurs="unbounded">
<xs:element name="link" type="link" minOccurs="0" maxOccurs="unbounded"/>
...
</xs:sequence>
</xs:sequence>
</xs:choice>
</xs:sequence>
...
to create the sequence linkElement of type Link and sequence of choices:
#XmlElement(name = "link")
protected List<Link> linkElement;
...
#XmlElements({
#XmlElement(name = "link", type = Link.class),
...
})
protected List<Object> linkAndBookmarkAndCreditWords;
but when I try a JAXB external binding file with the likes of:
<jxb:bindings node="//xs:complexType[#name='credit']//xs:sequence//xs:element[#name='link']" >
<jxb:property name="linkElement" />
</jxb:bindings>
I get the error:
[ERROR] XPath evaluation of "...[#name='link']" results in too many (2) target nodes
How can I distinguish only the first "link" node as I do in the internal bindings?
You XPath-expression is not precise enough. These // mean "anywhere below current node". This includes both of your link elements.
Try making your XPath-expression more precise, something along the lines:
xs:complexType[#name='credit']/xs:sequence/xs:element[#name='link']

Using keyRef in XSD : How to refer a key located in a different XSD (out of scope error)

My system parses two XML files (via JAXB unmarshalling and xjc generated code)
componentModel.xml : generated from a modeling tool
detailedDesign.xml : manual, to add informations
In order to avoid to code checks upon content and structures, each file is validated with its own XSD
componentModel.xsd
detailedDesign.xsd
Both of these xsd inclulde "utilities.xsd" where common complex and simple types are defined
All works well
I now want to add consistency check :
unicity of Ids (names of components)
components in "detailsDesign" must refers one of the components in "componentModel" via the "name" and "nameRef" attributes
Here are the structures (i've simlplified names and structures in files to show only relevant informations)
Note : as you can see, i don't use any namespace except the default one
componentModel.xml
<?xml version="1.0" encoding="UTF-8"?>
<componentModel>
<components>
<component name="id1"> ... </component>
<component name="id1"> ... </component>
<component name="id2"> ... </component>
</components>
</componentModel>
componentModel.xsd
<?xml version="1.0"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" >
<xs:include schemaLocation="utilities.xsd" />
<xs:complexType name="CMComponent">
<xs:complexContent>
...
<xs:attribute name="name" type="MUUpperFirstName" use="required" />
</xs:complexContent>
</xs:complexType>
<xs:complexType name="CMComponents">
<xs:sequence>
<xs:element name="component" type="CMComponent" minOccurs="0" maxOccurs="unbounded" />
</xs:sequence>
</xs:complexType>
<xs:complexType name="CMComponentModel">
<xs:complexContent>
<xs:sequence>
<xs:element name="components" type="CMComponents">
<!-- Key used to check "name" unicity and as a ref by nameRef attribute in detailedDesign model -->
<xs:key name="componentNameKey">
<xs:selector xpath="component" />
<xs:field xpath="#name" />
</xs:key>
</xs:element>
<xs:element name="functionalChains" minOccurs="0" maxOccurs="1" />
</xs:sequence>
<xs:attribute name="name" type="MUModelName" use="required" />
</xs:complexContent>
</xs:complexType>
<xs:element name="componentModel" type="CMComponentModel" />
</xs:schema>
utilities.xsd
<?xml version="1.0"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:simpleType name="MUString">
<xs:restriction base="xs:string"/>
</xs:simpleType>
<xs:simpleType name="MUUpperFirstName">
<xs:restriction base="MUString">
<xs:pattern value="([A-Z]+[a-zA-Z0-9]*[.])*[A-Z]+[a-zA-Z0-9]*"/>
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="MUReferenceName">
<xs:restriction base="MUString">
<xs:pattern value="([A-Z]+[a-zA-Z0-9]*[.])*[a-zA-Z]+[a-zA-Z0-9]*"/>
</xs:restriction>
</xs:simpleType>
</xs:schema>
detailedDesign.xml
<?xml version="1.0" encoding="UTF-8"?>
<detailedDesignModel>
<components>
<component nameRef="id1"> ... </component>
<component nameRef="id2"> ... </component>
<component nameRef="id3"> ... </component>
</components>
</detailedDesignModel>
detailedDesign.xsd
<?xml version="1.0"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:include schemaLocation="utilities.xsd" />
<xs:include schemaLocation="componentModel.xsd" />
<xs:complexType name="DDMComponent">
<xs:complexContent>
...
<xs:attribute name="nameRef" type="MUReferenceName" use="required" />
</xs:complexContent>
</xs:complexType>
<xs:complexType name="DDMComponents">
<xs:sequence>
<xs:element name="component" type="DDMComponent" minOccurs="0" maxOccurs="unbounded" />
</xs:sequence>
</xs:complexType>
<xs:complexType name="DDMDetailDesignModel">
<xs:complexContent>
<xs:sequence>
<xs:element name="components" type="DDMComponents">
<xs:keyref name="componentNameKeyRef" refer="componentNameKey">
<xs:selector xpath="component" />
<xs:field xpath="#nameRef" />
</xs:keyref>
</xs:element>
</xs:sequence>
</xs:complexContent>
</xs:complexType>
<xs:element name="detailDesignModel" type="DDMDetailDesignModel" />
</xs:schema>
It works for unicity of 'name' attribute among components (error retrieved from ValidationEventHandler set on unmarshaller) :
Duplicate key value [id1] declared for identity constraint of element "components".
But i can't get the "keyref" functionnality working (error retrieved from ValidationEventHandler set on unmarshaller) :
Identity Constraint error: identity constraint "KeyRef#272ed83b" has a keyref which refers to a key or unique that is out of scope.
How can i make the keyRef to see the Key defined in the orther XSD file
Thanks
Matth

JAXB: xjc and fixed values for attributes of derived types

I'm trying to create an xsd with a type hierarchy.
What I'm hoping to archieve is that the subtypes fill the base type's attributes with a certain value.
This is my best result:
<xs:complexType name="base_type">
<xs:attribute name="att" use="required" type="xs:string" />
</xs:complexType>
<xs:complexType name="type1_t">
<xs:complexContent>
<xs:restriction base="base_type">
<xs:attribute name="att" fixed="value1" use="required" type="xs:string" />
</xs:restriction>
</xs:complexContent>
</xs:complexType>
<xs:complexType name="type2_t">
<xs:complexContent>
<xs:restriction base="base_type">
<xs:attribute name="att" fixed="value2" use="required" type="xs:string" />
</xs:restriction>
</xs:complexContent>
</xs:complexType>
The "att" attribute is made available by base_type, and in elements of type1_t and type2_t, I'd like them set to "value1" and "value2", respectively.
The container element looks like this:
<xs:element name="root">
<xs:complexType>
<xs:choice maxOccurs="unbounded">
<xs:element name="type1" type="type1_t" />
<xs:element name="type2" type="type2_t" />
</xs:choice>
</xs:complexType>
</xs:element>
Now I'm running xjc to generate Java classes for this code, but the "fixed" attribute is not represented in what I get in the Type1T.java, which consists only of
#XmlAccessorType(XmlAccessType.FIELD)
#XmlType(name = "type1_t")
public class Type1T extends BaseType { }
I would have expected
{
#Override public String getAtt() { return "value1"; }
}
?
That is (almost) what gets generated when the type is generated by itself (ie not as an extension of a base type).
I'm I doing something wrong? Is what I'm trying to do just not possible?
My goal is to automatically generate all java code from xsd; otherwise I suppose a way to implement this would be to code the fixed values in the created ObjectFactory methods for each class manually. However, then I would need to prevent ObjectFactory from getting generated every time...
Any hints? Tips? Thoughts?

xml with same element with different value need a schema

For the following xml need a schema.
<?xml version="1.0" encoding="UTF-8"?>
<overall_operation>
<operation type="list_products">
<ops_description>Listing all the products of a company</ops_description>
<module>powesystem</module>
<comp_name>APC</comp_name>
<prod_price>50K$</prod_price>
<manf_date>2001</manf_date>
<pool_name>Electrical</pool_name>
<fail_retry>2</fail_retry>
<storage_type>avialble</storage_type>
<storage_check>false</storage_check>
<api_type>sync</api_type>
<product_name>transformer</product_name>
</operation>
<operation type="search_product">
<ops_description>Search the products of a company from the repository</ops_description>
<module>high-voltage</module>
<module>powesystem</module>
<comp_name>APC</comp_name>
<pool_name>Electrical</pool_name>
<fail_retry>2</fail_retry>
<storage_type>avialble</storage_type>
<storage_check>false</storage_check>
<api_type>sync</api_type>
<product_name>setup-transformer</product_name>
</operation>
</overall_operation>
Here different elements with operation like list_products,search_products and so on.
Each element will have some common attributes such as ops_description,module and so on.
Also some of the unique attributes for each element such as prod_price,manf_date etc.
I want to have a xml schema to validate. Some of the attributes also optional.
I tried using abstract and derived but could not make it work.
What you want to achieve is not possible with xml schema. The definition states that every element or attribute must be validated on its own and without reference to other elements or attributes.
The best solution you can get is to group optional but dependent elements:
<?xml version="1.0" encoding="utf-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="overall_operation">
<xs:complexType>
<xs:sequence>
<xs:element name="operation" minOccurs="0" maxOccurs="unbounded">
<xs:complexType>
<xs:sequence>
<xs:element name="ops_description" />
<xs:element name="module" minOccurs="1" maxOccurs="2" />
<xs:element name="comp_name" />
<xs:group ref="price_and_date" minOccurs="0" maxOccurs="1" />
<xs:element name="pool_name" />
<xs:element name="fail_retry" />
<xs:element name="storage_type" />
<xs:element name="storage_check" />
<xs:element name="api_type" />
<xs:element name="product_name" />
</xs:sequence>
<xs:attribute name="type" type="xs:string" />
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:group name="price_and_date">
<xs:sequence>
<xs:element name="prod_price" />
<xs:element name="manf_date" />
</xs:sequence>
</xs:group>
</xs:schema>
Use minOccurs and maxOccurs attributes to control optional elements and groups.

JAXB generating wrong Namespace

I have a xsd (lets name it as afb) which imports another xsd (lets name it as kts). And I refer to an element of kts.xsd in afb.xsd along with correct namespaces.
But when I generate the classes using JAXB, the namespace for refered element is wrong.
I mean, the referred element should have kts namespace where as it is having afb namespace.
Because of which validating my XML against this xsd is failing also not able to bind the xml data into the java models.
EX:
afb.xsd :
<xs:import namespace="http://www.boschkts.com" schemaLocation="kts.xsd"/>
<xs:element name="vehicle">
<xs:complexType>
<xs:sequence>
<xs:element ref="vType"/>
<xs:element name="RESULTS" type="kts:RESULTS" >
</xs:sequence>
</xs:complexType>
</xs:element>
kts:xsd :
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns="http://www.boschkts.com"
targetNamespace="http://www.boschkts.com" elementFormDefault="qualified">
<xs:complexType name="RESULTS">
<xs:sequence>
<xs:element name="SUMMARY" type="SUMMARY" minOccurs="0" />
</xs:sequence>
</xs:complexType>
Vehicle.java :
public class Vehicle {
#XmlElement(namespace = "http://www.boschafb.com", required = true)
protected String vType;
#XmlElement(name = "RESULTS", namespace = "http://www.boschafb.com", required = true)
protected Results results;
}
If I observe the Vehicle.java, the namespace of results property should have been "http://www.boschkts.com" instead of "http://www.boschafb.com"
If I change the namespace manually then binding the data from xml to java models works.
But still validating against the xsd fails with the error :
Caused by: org.xml.sax.SAXParseException: cvc-complex-type.2.4.a: Invalid content was found starting with element 'kts:RESULTS'. One of '{"http://www.boschafb.com":RESULTS}' is expected.
Can anybody point what I might be missing in the xsd? or is it the way jaxb generates and I have to modify the classes manually?
Regards,
Satya
I'm assuing your abf.xsd starts with
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns="http://www.boschafb.com"
targetNamespace="http://www.boschafb.com" elementFormDefault="qualified">
With elementFormDefault set to qualified, all element declarations, even nested ones, belong to the specified target namespace. Note that this applies only to elements, a referenced type does not affect the namespace of the element referencing it.
A solution would be to define an element instead of a type in 'kts.xsd' and referencing this element in your first schema:
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns="http://www.boschkts.com"
targetNamespace="http://www.boschkts.com" elementFormDefault="qualified">
<xs:element name="RESULTS">
<xs:complexType>
<xs:sequence>
<xs:element name="SUMMARY" type="SUMMARY" minOccurs="0" />
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns="http://www.boschafb.com"
targetNamespace="http://www.boschafb.com" elementFormDefault="qualified"
xmlns:kts="http://www.boschkts.com">
<xs:import namespace="http://www.boschkts.com" schemaLocation="kts.xsd"/>
<xs:element name="vehicle">
<xs:complexType>
<xs:sequence>
<xs:element ref="vType"/>
<xs:element ref="kts:RESULT"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
Try using an include instead of an import like so:
<xs:include schemaLocation="kts.xsd"/> instead of <xs:import namespace="http://www.boschkts.com" schemaLocation="kts.xsd"/>
This style causes far less problems with intra-namespace includes.

Resources