I have a XSD with XML elements A, B, and C.
I would like these to appear in a parent element in this way:
A and B can appear any times, C only once, optionally.
The order does not matter, but A and B should ideally be "together",
(so it's rather (A*), C?, (B*) | (B*), C?, (A*)), but the "A and B together" is not necessary).
How can I achieve that with XSD?
Actual XSD what I have tried:
<!-- Hint -->
<xs:element name="hint">
<xs:complexType mixed="true">
<xs:sequence>
<xs:choice>
<xs:element ref="tag" minOccurs="0" maxOccurs="unbounded"/>
<xs:element ref="link" minOccurs="0" maxOccurs="unbounded" />
</xs:choice>
<xs:sequence>
<xs:element name="message" minOccurs="0" maxOccurs="1"/>
</xs:sequence>
<xs:choice>
<xs:element ref="tag" minOccurs="0" maxOccurs="unbounded"/>
<xs:element ref="link" minOccurs="0" maxOccurs="unbounded"/>
</xs:choice>
</xs:sequence>
</xs:complexType>
</xs:element>
But that gives me
cos-nonambig: <ns>:link and <ns>:link (or elements from their substitution group) violate "Unique Particle Attribution". During validation against this schema, ambiguity would be created for those two particles.
Basically, the need is to have any mix of A, B, C, where C appears
only once.
XSD 1.1 Solution
<?xml version="1.0" encoding="utf-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:vc="http://www.w3.org/2007/XMLSchema-versioning"
vc:minVersion="1.1">
<xs:complexType name="SolutionType">
<xs:choice minOccurs="0" maxOccurs="unbounded">
<xs:element name="A"/>
<xs:element name="B"/>
<xs:element name="C"/>
</xs:choice>
<xs:assert test="count(c) <= 1"/>
</xs:complexType>
</xs:schema>
The above xs:assertion assumes that you mean "C appears at most once" but can easily be adjusted to require C to appear exactly once.
A and B can appear any times, C only once, optionally. The order does
not matter, but A and B should ideally be "together"
XSD 1.0 Solution
You'll have to impose an ordering to avoid violating Unique Particle Attribution:
<?xml version="1.0" encoding="utf-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:complexType name="SolutionType">
<xs:sequence>
<xs:element name="A" minOccurs="0" maxOccurs="unbounded"/>
<xs:element name="C" minOccurs="0"/>
<xs:element name="B" minOccurs="0" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
</xs:schema>
At least this achieves your preference toward keeping A and B together.
The "Unique Particle Attribution" basically means that every element during validation needs to be deterministically assignable to certain XSD "branch". And that can be checked when validating the XSD.
I found out that the (only?) way to avoid abiguity is to list all combinations of A,B,C in a <xs:choice>, while setting minOccurs="1" as appropriate to break the ambiguity. That gives quite a few choices, but for 3 elements, still doable.
This is for the case where I leave 'C' in the beginning:
<xs:sequence>
<xs:element name="message" minOccurs="0" maxOccurs="1"/>
<xs:choice>
<xs:sequence>
<xs:element ref="link" minOccurs="1" maxOccurs="unbounded" />
<xs:element ref="tag" minOccurs="0" maxOccurs="unbounded"/>
</xs:sequence>
<xs:sequence>
<xs:element ref="tag" minOccurs="1" maxOccurs="unbounded"/>
<xs:element ref="link" minOccurs="0" maxOccurs="unbounded" />
</xs:sequence>
<xs:sequence/>
</xs:choice>
</xs:sequence>
Not closing this question, I believe there's a better option even in XSD 1.0.
Related
I want to model a container that has a list of references by id in enterprise architect.
A xsd is generated from that model.
<?xml version="1.0" encoding="utf-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="Container" type="Container"/>
<xs:complexType name="Container">
<xs:sequence>
<xs:element name="Element" type="Element" minOccurs="0" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
<xs:element name="Element" type="Element"/>
<xs:complexType name="Element">
<xs:sequence>
<xs:element name="Identifier" type="xs:ID" minOccurs="1" maxOccurs="1"/>
<xs:element name="Name" type="xs:string" minOccurs="1" maxOccurs="1"/>
</xs:sequence>
</xs:complexType>
</xs:schema>
Is it possible to find settings so such that a list of Id is generated?
(Not a list of full instances like it is now)
Here are the settings of the aggregation:
The goal is to have a list of ID in the container generated from the association and have the possibility to generate java code from the xsd that has a list of element, not ID.
<?xml version="1.0" encoding="utf-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="Container" type="Container"/>
<xs:complexType name="Container">
<xs:sequence>
<xs:element name="ElementRef" type="xs:IDREF" minOccurs="0" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
<xs:element name="Element" type="Element"/>
<xs:complexType name="Element">
<xs:sequence>
<xs:element name="Identifier" type="xs:ID" minOccurs="1" maxOccurs="1"/>
<xs:element name="Name" type="xs:string" minOccurs="1" maxOccurs="1"/>
</xs:sequence>
</xs:complexType>
</xs:schema>
So, the XSD shall have a list of IDREF, so that the java code generated from that shall have either a list of Identifiers or even better a list of Element.
Edit: added example of target xsd.
with xsd, is there a way in which we can define an element that is repeated an even number of times? with my information it is not possible with the attributes minOcurs and maxOccurs.
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" >
<xs:element name="A">
<xs:complexType>
<xs:sequence>
<xs:element name="B" maxOccurs="?" minOccurs="?"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
How about this:
<xs:sequence minOccurs="0" maxOccurs="unbounded">
<xs:element name="B" maxOccurs="2" minOccurs="2"/>
</xs:sequence>
I it possible to make a choice scenario, like (A or B or Both). If yes, how can this be done with the following elements?
<xs:element name="a" type="typeA" />
<xs:element name="b" type="typeB" />
Hope you can help.
Regards,
Nima
You can see XSD "one or both" choice construct leads to ambiguous content model
<xs:schema xmlns:xs="...">
<xs:element name="a" type="typeA" />
<xs:element name="b" type="typeB" />
<xs:element name="...">
<xs:complexType>
<xs:sequence>
<xs:choice>
<xs:sequence>
<xs:element ref="a"/>
<xs:element ref="b" minOccurs="0"/>
</xs:sequence>
<xs:element ref="b"/>
</xs:choice>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
If you look at the following xsd fragment you can conclude that the corresponding xml will first contain cars followed by busses eg:
car,car,bus,bus
HOWEVER I want the xml to be able to contain
car,bus,car,bus
What change do I need to make in the xsd below in order to achieve this?
<xs:element name="body">
<xs:complexType>
<xs:sequence>
<xs:element name="session" type="tns:session" />
<xs:element minOccurs="0" maxOccurs="unbounded" name="car" type="tns:car" />
<xs:element minOccurs="0" maxOccurs="unbounded" name="bus" type="tns:bus" />
</xs:sequence>
</xs:complexType>
</xs:element>
It's a bit cumbersome, but you might achieve what you're looking for like this:
create a <xs:choice> element with your car and bus elements inside; this defines that one of the contained elements can be used
make sure to have the attribtues minOccurs=1 and maxOccurs=unbounded on that <xs:choice> - this gives you any number of either car or bus elements - any number, any combination
So your XML schema would look something like this (I added some stuff just to be able to generate a sample XML and verify it works - tweak as needed):
<?xml version="1.0" encoding="utf-8"?>
<xs:schema elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="body">
<xs:complexType>
<xs:choice minOccurs="0" maxOccurs="unbounded">
<xs:element minOccurs="0" maxOccurs="unbounded" name="car" type="CarType" />
<xs:element minOccurs="0" maxOccurs="unbounded" name="bus" type="BusType" />
</xs:choice>
</xs:complexType>
</xs:element>
<xs:complexType name="CarType">
<xs:sequence>
<xs:element name="Maker" type="xs:string" />
</xs:sequence>
</xs:complexType>
<xs:complexType name="BusType">
<xs:sequence>
<xs:element name="Maker" type="xs:string" />
<xs:element name="Capacity" type="xs:int" />
</xs:sequence>
</xs:complexType>
</xs:schema>
use <xs:any> insted of <xs:sequence>
I have an XML Schema that looks like this:
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="root">
<xs:complexType>
<xs:sequence>
<xs:element name="A" minOccurs="0" maxOccurs="1"/>
<xs:element name="B" minOccurs="0" maxOccurs="1"/>
<xs:element name="C" minOccurs="0" maxOccurs="32"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
The following is valid according to this schema:
<root xsi:noNamespaceSchemaLocation="MySchema.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
</root>
However, I'd like to make the above XML invalid.
More specifically, I'd like to require:
1. that the <root> have at least one child element, be it an <A>, a <B>, or a <C>, and
2. that the <root> have at most one <A> child, and at most one <B> child.
Suggestions?
Solution is:
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="root">
<xs:complexType>
<xs:choice>
<xs:sequence>
<xs:element name="A"/>
<xs:element name="B" minOccurs="0"/>
<xs:element name="C" minOccurs="0" maxOccurs="32"/>
</xs:sequence>
<xs:sequence>
<xs:element name="B"/>
<xs:element name="C" minOccurs="0" maxOccurs="32"/>
</xs:sequence>
<xs:sequence>
<xs:element name="C" minOccurs="1" maxOccurs="32"/>
</xs:sequence>
</xs:choice>
</xs:complexType>
</xs:element>
</xs:schema>
How about using exactly one xs:choice of A, B, or C followed by 0 or more of each of them?
Ah, with your edit it would have to be something like a choice of A, AB, or B followed by 0 to 32 Cs. Yes?
Have you tried adding minOccurrs=1 to the xs:sequence?