EMF: Overriding XSD - xsd

I am writing XSD to generate Model Classes using EMF.
The XSD looks like:
<xsd:complexType name="DerivedType">
<xsd:complexContent mixed="false">
<xsd:extension base="ParentType">
<xsd:sequence>
<xsd:element ...../>
<xsd:element ...../>
</xsd:sequence>
<xsd:attribute .... />
</xsd:extension>
</xsd:complexContent>
</xsd:complexType>
Here the DerivedType is extending from ParentType.
ParentType contains another complex element 'cmplx'.
Now, I want to add another attribute to complex element ('cmplx').
I don't want to extend 'cmplx' as it will create a new class in EMF generated code against extending the 'cmplx' type.

You can add an element or attribute defining its type as follows:
<xs:element name="name" type="xs:string"/>
<xs:attribute name="name" type="xs:string" />
Can you be more specific? What kind of attribute would you like to add? Is it an attribute or is it an element?

Related

Can you have more than one indicator in an XSD complex element?

I'm trying to build a new schema to validate XML against for my job. But I'm having a hard time answering the question: can I and how do I create a complex element that has some elements that need to be in a set sequence and other subelements that do not? Ultimately I think I should be able to have opening and closing "sequence" tags and opening and closing "all" tags around two sets of elements, but xsd doesn't seem to like that. Here's what I have:
<xsd:complexType name="Original">
<xsd:sequence>
<xsd:element maxOccurs="1" minOccurs="1" name="AssetIdentifier" type="xsd:string">
<xsd:annotation>
<xsd:documentation>Definition: The Asset Identifier element is intended to
reflect the root of all following digital filenames.</xsd:documentation>
</xsd:annotation>
</xsd:element>
<xsd:element maxOccurs="1" minOccurs="0" name="ArchiveID" type="xsd:string">
<xsd:annotation>
<xsd:documentation>Definition: The Filename element in this section is
intended to reflect the root of all the following derivative digital
filenames.</xsd:documentation>
</xsd:annotation>
</xsd:element>
<xsd:element maxOccurs="1" minOccurs="1" name="Title" type="xsd:string">
<xsd:annotation>
<xsd:documentation>Definition: The known title of the asset. If no title is
known, one can be assigned; a number or letter sequence, whichever is
the most logical. Using the value "unknown" is also
acceptable.</xsd:documentation>
</xsd:annotation>
</xsd:element>
<xsd:element maxOccurs="1" minOccurs="1" name="RecordDate" type="xsd:date">
<xsd:annotation>
<xsd:documentation>Definition: The actual recording date of the asset.
Estimates, partial dates, and date ranges (i.e. 19XX, Feb. 19-24,
1934-1935, etc.) are allowable, as is 'unknown'. Best practice, when
applicable, is to use the YYYY-MM-DD format in accordance with ISO 8601.
Even partial dates, i.e. 1990-05 should adhere to this
format.</xsd:documentation>
</xsd:annotation>
</xsd:element>
<xsd:element maxOccurs="1" minOccurs="1" name="FormatType" type="xsd:string">
<xsd:annotation>
<xsd:documentation>Definition: The format of the analog asset, i.e. Open
Reel, Grooved Disc, DAT, Cassette, VHS, 16mm film, EIAJ,
etc.</xsd:documentation>
<xsd:documentation>Best Practice: The MediaPreserve maintains a list of
controlled vocabularies organized by media type at: www.dontknowyet.com.
However, MP opted to meake this an unrestricted element in the event
that other ogranizations have their own controlled vocabularies in
place.</xsd:documentation>
</xsd:annotation>
</xsd:element>
</xsd:sequence>
<xsd:all>
<xsd:element maxOccurs="1" minOccurs="0" name="StockBrand" type="xsd:string">
<xsd:annotation>
<xsd:documentation>If known definitively</xsd:documentation>
</xsd:annotation>
</xsd:element>
<xsd:element maxOccurs="1" minOccurs="0" name="TapeModel" type="xsd:string">
<xsd:annotation>
<xsd:documentation>If applicable. Usually applies to DAT tapes, open reels,
and wire recordings.</xsd:documentation>
</xsd:annotation>
</xsd:element>
<xsd:element maxOccurs="1" minOccurs="0" name="TapeWidth" type="xsd:string">
<xsd:annotation>
<xsd:documentation>Typically only applicable for open reel
audio</xsd:documentation>
</xsd:annotation>
</xsd:element>
</xsd:all>
XSDs unfortunately do not allow what you're trying to do (combine <sequence/> and <all /> inside a single complex type or element). You might be able to achieve something similar with a nested content model, but note you can't nest <all> except under another <all />, otherwise you must define it in another element. You can however, nest either <sequence> or <choice> under each other.
From my understanding of XSDs, you have 3 viable options.
The first is to nest all the elements you want under <all /> to be contained within their own sub-element:
<xs:complexType name="Original">
<xs:sequence>
<!-- AssetIdentifier to FormatType left out for brevity -->
<xs:element name="Misc">
<xs:complexType>
<xs:all>
<xs:element maxOccurs="1" minOccurs="0" name="StockBrand" type="xs:string" />
<xs:element maxOccurs="1" minOccurs="0" name="TapeModel" type="xs:string" />
<xs:element maxOccurs="1" minOccurs="0" name="TapeWidth" type="xs:string" />
</xs:all>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
<!-- For the above, valid XML would be: -->
<Original>
<AssetIdentifier>AssetIdentifier0</AssetIdentifier>
<Title>Title0</Title>
<RecordDate>2006-05-04</RecordDate>
<FormatType>FormatType0</FormatType>
<Misc>
<!-- Optional & order doesn't matter -->
<StockBrand>what</StockBrand>
<TapeWidth>1290</TapeWidth>
<TapeModel>Hey</TapeModel>
</Misc>
</Original>
Second is to nest those elements under another <sequence />, which allows you to forgo specifying another sub-element, but now requires the elements appear in order as specified in the schema. Note that the nested sequence itself can be optional.
<xs:complexType name="Original">
<xs:sequence>
<!-- AssetIdentifier to FormatType left out for brevity -->
<xs:sequence minOccurs="0">
<xs:element maxOccurs="1" minOccurs="0" name="StockBrand" type="xs:string" />
<xs:element maxOccurs="1" minOccurs="0" name="TapeModel" type="xs:string" />
<xs:element maxOccurs="1" minOccurs="0" name="TapeWidth" type="xs:string" />
</xs:sequence>
</xs:sequence>
</xs:complexType>
<!-- For the above, valid XML would be: -->
<Original>
<AssetIdentifier>AssetIdentifier0</AssetIdentifier>
<Title>Title0</Title>
<RecordDate>2006-05-04</RecordDate>
<FormatType>FormatType0</FormatType>
<!-- Optional below, but must be ordered -->
<StockBrand>what</StockBrand>
<TapeModel>Hey</TapeModel>
<TapeWidth>1290</TapeWidth>
</Original>
There's a third option that is a bit of a 'hack', but still allows specifying elements go unordered, still remain optional, yet still appear adjacent to the other mandatory, in-order elements. This nests a choice (with maxOccurs="3") under sequence, inside the parent sequence (sequence > sequence > choice):
<xs:complexType name="Original">
<xs:sequence>
<!-- AssetIdentifier to FormatType left out for brevity -->
<xs:sequence>
<xs:choice maxOccurs="3" minOccurs="0">
<xs:element name="StockBrand" type="xs:string"/>
<xs:element name="TapeModel" type="xs:string"/>
<xs:element name="TapeWidth" type="xs:string"/>
</xs:choice>
</xs:sequence>
</xs:sequence>
</xs:complexType>
<!-- For the above, valid XML would be: -->
<Original>
<AssetIdentifier>AssetIdentifier0</AssetIdentifier>
<Title>Title0</Title>
<RecordDate>2006-05-04</RecordDate>
<FormatType>FormatType0</FormatType>
<!-- Optional, unordered, but there's a catch: -->
<TapeWidth>1290</TapeWidth>
<StockBrand>what</StockBrand>
<TapeModel>Hey</TapeModel>
</Original>
There's a catch with this 3rd option however, the maxOccurs="3" on the <choice /> element renders the minOccurs and maxOccurs on the child elements (StockBrand, TapeModel and TapeWidth) meaningless; which means those elements, while still remaining optional, can now appear more than once, so long as the cumulative total of elements is still 3 or less:
This becomes valid (2 of the same element + 1 more):
<TapeWidth>1290</TapeWidth>
<TapeWidth>1291</TapeWidth>
<TapeModel>Hey</TapeModel>
And this is still valid (3 of the same):
<TapeWidth>1290</TapeWidth>
<TapeWidth>1291</TapeWidth>
<TapeWidth>1292</TapeWidth>
And also this (just 1 occurence of 1 element):
<StockBrand>1290</StockBrand>
You could probably try to find another option by fiddling with the combination of sequence and choice nesting, but it's best practice to keep your schemas simple. Personally I would recommend the first 2 options over the third purely to keep your schema simple.

Jaxb behaviour is odd

I am trying to marshall and unmarshal gpx files with an extension. The gpx schema allows to have extension added in the extensions tag example:
<trkpt lat="51.219983" lon="6.765224">
<ele>52.048584</ele>
<time>2009-06-19T10:13:04Z</time>
<extensions>
<gpxdata:hr>164</gpxdata:hr>
<gpxdata:cadence>99</gpxdata:cadence>
</extensions>
</trkpt>
The GPX file is correct and passes unmarshalling like this:
JAXBContext jaxbContext = JAXBContext.newInstance(GpxType.class, com.cluetrust.xml.gpxdata._1._0.ObjectFactory.class);
Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
File file = new File("src/test/resources/gpx-example.gpx");
JAXBElement<GpxType> unmarshal = (JAXBElement<GpxType>) unmarshaller.unmarshal(file);
GpxType gpx = unmarshal.getValue();
Two things for me are odd. First off all I have to unmarshal to a JAXBElement and cannot go straight to GpxType, I have to go to the JAXBElement first.
Second of all and that is (for me the biggest problem) once I have the GpxType object. Part is indeed done, but the extensions are not:
ExtensionsType extensions = gpx.getExtensions();
List<Object> extensionsAny = extensions.getAny();
for (Object object : extensionsAny){
System.out.println(object.getClass());
if (object instanceof JAXBElement) {
JAXBElement element = (JAXBElement) object;
LapType lapType = (LapType) element.getValue();
System.out.println(lapType.getStartTime());
}
It seems I have to jump through some hoops here. I have setup a very small project on github where this is shown jaxbproblem. The complete example GPX file i am using is there too. The namespaces in it are correct:
<gpx xmlns="http://www.topografix.com/GPX/1/1"
xmlns:gpxdata="http://www.cluetrust.com/XML/GPXDATA/1/0"
creator="pytrainer http://sourceforge.net/projects/pytrainer" version="1.1">
EDIT:
Relevant part in the schema is :
<xsd:element name="lap" type="lapType">
<xsd:annotation>
<xsd:documentation>
Lap is used to contain information about an individual lap of activity.
Depending upon the device, this may contain a variety of additional information.
Depending upon the device, this may be contained within a run or course.
</xsd:documentation>
</xsd:annotation>
</xsd:element>
and:
<xsd:complexType name="lapType">
<xsd:sequence>
<xsd:element name="index" type="xsd:int" minOccurs="0" maxOccurs="1">
<xsd:annotation><xsd:documentation>The index of the lap in the internal list.</xsd:documentation></xsd:annotation>
</xsd:element>
<xsd:element name="startPoint" type="locationType" minOccurs="0" maxOccurs="1">
<xsd:annotation><xsd:documentation>The starting point of the lap in Lat/Long</xsd:documentation></xsd:annotation>
</xsd:element>
<xsd:element name="endPoint" type="locationType" minOccurs="0" maxOccurs="1">
<xsd:annotation><xsd:documentation>The ending point of the lap in Lat/Long</xsd:documentation></xsd:annotation>
</xsd:element>
<xsd:element name="startTime" type="xsd:dateTime" minOccurs="0" maxOccurs="1">
<xsd:annotation><xsd:documentation>The starting time of the lap</xsd:documentation></xsd:annotation>
</xsd:element>
<xsd:element name="elapsedTime" type="xsd:float" minOccurs="0" maxOccurs="1">
<xsd:annotation><xsd:documentation>The total elapsed time of the lap in seconds</xsd:documentation></xsd:annotation>
</xsd:element>
<xsd:element name="calories" type="xsd:nonNegativeInteger" minOccurs="0" maxOccurs="1">
<xsd:annotation><xsd:documentation>The number of calories burned during the lap</xsd:documentation></xsd:annotation>
</xsd:element>
<xsd:element name="distance" type="xsd:float" minOccurs="0" maxOccurs="1">
<xsd:annotation><xsd:documentation>Distance (in m) covered during the lap</xsd:documentation></xsd:annotation>
</xsd:element>
<xsd:element name="trackReference" type="trackReferenceType" minOccurs="0" maxOccurs="1">
<xsd:annotation><xsd:documentation>Reference information for the track which corresponds to this lap</xsd:documentation></xsd:annotation>
</xsd:element>
<xsd:element name="summary" type="summaryType" minOccurs="0" maxOccurs="unbounded">
<xsd:annotation><xsd:documentation>Performance summary elements summarizing different performance measurements, such as cadence, hr, etc.</xsd:documentation></xsd:annotation>
</xsd:element>
<xsd:element name="trigger" type="triggerType" minOccurs="0" maxOccurs="1">
<xsd:annotation><xsd:documentation>The trigger of the lap. On some devices, the lap may be manual or automatic based on attributes known by the device.</xsd:documentation></xsd:annotation>
</xsd:element>
<xsd:element name="intensity" type="intensityKind" minOccurs="0" maxOccurs="1">
<xsd:annotation><xsd:documentation>The intensity of the lap (whether resting or active)</xsd:documentation></xsd:annotation>
</xsd:element>
</xsd:sequence>
</xsd:complexType>
This is just one of the many types that are being introduced with this schema that can be found here
What am I doing wrong?

XMLSchema - Element refers to itself - how to do it?

I have a task where I need to create an element "Worker" which has 0 or more subelements "subordinate". I have to use key and keyref to create the references. I can't figure out how make the references "work". Here's what I've written so far:
<xsd:element name="Workers">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="Worker" maxOccurs="unbounded">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="name" type="xsd:string"/>
<xsd:element name="subordinate" minOccurs="0" maxOccurs="unbounded"/>
</xsd:sequence>
<xsd:attribute name="identyfikator" type="PESEL" use="required"/>
</xsd:complexType>
</xsd:element>
</xsd:sequence>
</xsd:complexType>
<xsd:key name="id">
<xsd:selector xpath="Worker"/>
<xsd:field xpath="#identyfikator"/>
</xsd:key>
<xsd:keyref name="subordinate_ref" refer="id">
<xsd:selector xpath="Worker/subordinate"/>
<xsd:field xpath="#identyfikator"/>
</xsd:keyref>
</xsd:element>
PESEL is my own type and the key restriction works well as I am unable to create two workers with the same key in XML document. However, I can create anything as "subordinate" element and no warnings will be displayed. As I understand, in case of such reference I should be only able to add workers as subordinates if they already exist, right? How do I create proper reference?
This is my first time working with XMLSchema so sorry if the code is messy.
Thanks in advance!
Make a Worker ComplexType and have Worker and Subordinate both be of that type.
Approximately like so:
<!-- Define the below where appropriate. -->
<xsd:element name="Worker" type="WorkerType" />
<xsd:complexType name="WorkerType">
<xsd:sequence>
<xsd:element name="name" type="xsd:string"/>
<xsd:element name="subordinate" type="WorkerType" minOccurs="0" maxOccurs="unbounded"/>
</xsd:sequence>
<xsd:attribute name="identyfikator" type="PESEL" use="required"/>
</xsd:complexType>
Also, if you want items to have a unique id, then consider using (or extending) the xsd:ID datatype. This gives you free uniqueness and referential checks using xsd:IDREF.
<xsd:attribute name="identyfikator" type="xsd:ID" use="required"/>

xsd restriction in extended element

Suppose I have an element A and an element B extended from A as shown below.
<xsd:complexType name="A">
<xsd:sequence>
<xs:element name="desiredVariable" type="xs:string"/>
</xsd:sequence>
<xsd:complexType>
<xsd:complexType name="B">
<xsd:complexContent>
<xsd:extension base="A">
<xsd:sequence>
<xs:element name="anotherVariable" type="xs:string"/>
</xsd:sequence>
</xsd:extension>
</xsd:complexContent>
</xsd:complexType>
I have an usecase where desiredVariable in A can take any value and the same desiredVariable in B should be a fixed value. ie I have to apply restiction on desiredValue in B. How can I do that?
In general, XML 1.0 does not allow conditional data. But you can acheive what you want through extensions. This is how to implement it in XML 1.0:
You'll need to define the base element as abstract if you want to enforce the limitations. In the XML file they will need to specify the extension they are implementing. You need to define your restrictions separately.
XSD:
<xsd:complexType name="A" abstract="true">
<xsd:sequence>
<xs:element name="desiredVariable" type="xs:string"/>
</xsd:sequence>
<xsd:complexType>
<xsd:complexType name="B">
<xsd:complexContent>
<xsd:extension base="A">
<xsd:restriction base="checksumType">
<xsd:sequence>
<xs:element name="desiredVariable" type="xs:string" fixed="FixedValue"/>
<xs:element name="anotherVariable" type="xs:stringLimitedType"/>
</xsd:sequence>
</xsd:restriction>
</xsd:extension>
</xsd:complexContent>
</xsd:complexType>
<xsd:simpleType name="stringLimitedType">
<xsd:restriction base="xs:string">
<xsd:pattern value="([a-zA-Z0-9])*"/>
</xsd:restriction>
</xsd:simpleType>
XML:
<A namespace:type="B">
...
</A>
See the following for more on abstraction and extensions:
XSD schema abstract type problem
I have heard there are more options when using XML 1.1.

How can I represent a sequence of an element with coupled attribute types in XSD?

I have the following requirements and am trying to determine how best to model the XSD to represent these requirements.
I have many instances of an XML element, say <box>. Each <box> has a required attribute t="[box-type]" and each box with a specific type, say t="tall" has another required attribute v="10" which represents the height of the tall box. All <box>es have both t and v attributes, but the restriction on what values are accepted for their v attributes depends on the value of their t attribute.
For example, take the following XML:
<box t="tall" v="10"/>
<box t="named" v="George"/>
<box t="colored" v="green"/>
Now, in my XSD I need to be able represent a sequence of such elements. My thought was to do something like the following which just lists out all of the allowed box types in my sequence (at the end of the following snippet):
<xsd:simpleType name="box_types">
<xsd:restriction base="xsd:token">
<xsd:enumeration value="tall" />
<xsd:enumeration value="named" />
<xsd:enumeration value="colored" />
</xsd:restriction>
</xsd:simpleType>
<!--Box base-->
<xsd:complexType name="box_type">
<xsd:attribute name="t" use="required" type="box_types"/>
<xsd:attribute name="v" use="required"/>
</xsd:complexType>
<!--Box concrete types-->
<xsd:complexType name="tall_box_type">
<xsd:complexContent>
<xsd:extension base="box_type">
<xsd:attribute name="t" fixed="tall" use="required"/>
<xsd:attribute name="v" type="xsd:int" use="required"/>
</xsd:extension>
</xsd:complexContent>
</xsd:complexType>
<xsd:complexType name="named_box_type">
<xsd:complexContent>
<xsd:extension base="box_type">
<xsd:attribute name="t" fixed="named" use="required"/>
<xsd:attribute name="v" type="xsd:string" use="required"/>
</xsd:extension>
</xsd:complexContent>
</xsd:complexType>
<xsd:complexType name="colored_box_type">
<xsd:complexContent>
<xsd:extension base="box_type">
<xsd:attribute name="t" fixed="colored" use="required"/>
<xsd:attribute name="v" type="xsd:token" use="required"/>
</xsd:extension>
</xsd:complexContent>
</xsd:complexType>
<!--And finally, the place where boxes show up-->
<xsd:complexType name="box_usage">
<xsd:sequence>
<xsd:element name="box" type="tall_box_type"/>
<xsd:element name="box" type="named_box_type"/>
<xsd:element name="box" type="colored_box_type"/>
</xsd:sequence>
</xsd:complexType>
Unfortunately, that is not a valid XSD - VS gives me the several errors, the most unfortunate being Elements with the same name and in the same scope must have the same type. Any advice on how I can represent these t/v coupled attribute restrictions in an XSD?
XML Schema 1.0 can't validate dependencies between values. Your options are:
Change your XML. For instance, use tallBox, colorBox and nameBox as element names.
Validate the general structure with XSD and validate values with program logic (or some other tool like Schematron or an XSLT stylesheet).
Use XML Schema 1.1, which can validate value constraints but is not commonly supported, yet.

Resources