Jaxb behaviour is odd - jaxb

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?

Related

XSD Choice with optional element

I have the following XSD template for the following:
<xsd:choice>
<xsd:element name="NilReport" type="ftc:CorrectableNilReport_Type">
<xsd:annotation>
<xsd:documentation xml:lang="en">Nil Report indicates that financial institution does not have accounts to report</xsd:documentation>
</xsd:annotation>
</xsd:element>
<xsd:sequence >
<xsd:element name="AccountReport" type="ftc:CorrectableAccountReport_Type" minOccurs="0" maxOccurs="unbounded">
<xsd:annotation>
<xsd:documentation>Detailed information for account report, such as account number and account balance</xsd:documentation>
</xsd:annotation>
</xsd:element>
<xsd:element name="PoolReport" type="ftc:CorrectablePoolReport_Type" minOccurs="0" maxOccurs="unbounded">
<xsd:annotation>
<xsd:documentation>Information about the pool of account holders with similar characteristics</xsd:documentation>
</xsd:annotation>
</xsd:element>
</xsd:sequence>
But the result so far doesn't go as it supposes to be.
Unexpected result
Here is my wanted result:
Expected result
How could i archive the expected result ? Please advice me.
Please note that both and are optional in this case.
Currently your choice lets you pick between the NilReport element and the sequence with the other two elements.
If you want to have the two other elements as children of the "sequence" you will have to create a containing element, and you need to define them as children of that element as follows.
<xsd:choice>
<xsd:element name="NilReport" type="ftc:CorrectableNilReport_Type">
<xsd:annotation>
<xsd:documentation xml:lang="en">Nil Report indicates
that financial institution does not have accounts to report</xsd:documentation>
</xsd:annotation>
</xsd:element>
<xsd:element name="NotNilReport">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="AccountReport" type="ftc:CorrectableAccountReport_Type"
minOccurs="0" maxOccurs="unbounded">
<xsd:annotation>
<xsd:documentation>Detailed information for account report, such
as account number and account balance</xsd:documentation>
</xsd:annotation>
</xsd:element>
<xsd:element name="PoolReport" type="ftc:CorrectablePoolReport_Type"
minOccurs="0" maxOccurs="unbounded">
<xsd:annotation>
<xsd:documentation>Information about the pool of account holders
with similar characteristics</xsd:documentation>
</xsd:annotation>
</xsd:element>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
</xsd:choice>

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.

Any order + constraints for each element

I am trying to create an XSD, which allows child elements to be in any order. But each child element has its own minOccurs and maxOccurs.
My XSD:
<xsd:complexType name="Samples">
<xsd:sequence >
<xsd:element name="Sample1" minOccurs="1" maxOccurs="1">
<xsd:complexType>
<xsd:simpleContent>
<xsd:extension base="xsd:boolean" />
</xsd:simpleContent>
</xsd:complexType>
</xsd:element>
<xsd:element name="Sample2" minOccurs="0" maxOccurs="unbounded">
<xsd:complexType>
<xsd:simpleContent>
<xsd:extension base="xsd:string" />
</xsd:simpleContent>
</xsd:complexType>
</xsd:element>
</xsd:sequence>
For Example a valid XML:
<Samples>
<Sample2></Sample2>
<Sample1></Sample1>
<Sample2></Sample2>
</Samples>
For Example a not valid XML (Sample1 can be choose only one time):
<Samples>
<Sample2></Sample2>
<Sample1></Sample1>
<Sample2></Sample2>
<Sample1></Sample1>
</Samples>
But i don't know, how i can mix the order, while all elements have its own constraint.
Thanks for help
What if you try this:
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<xsd:element name="Samples">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="Sample2" minOccurs="0" maxOccurs="unbounded"/>
<xsd:element name="Sample1" minOccurs="1" maxOccurs="1"/>
<xsd:element name="Sample2" minOccurs="0" maxOccurs="unbounded"/>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
</xsd:schema>
Of course, you should add your restrictions to each element:
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<xsd:complexType name="Sample1Type">
<xsd:simpleContent>
<xsd:extension base="xsd:boolean" />
</xsd:simpleContent>
</xsd:complexType>
<xsd:complexType name="Sample2Type">
<xsd:simpleContent>
<xsd:extension base="xsd:string" />
</xsd:simpleContent>
</xsd:complexType>
<xsd:element name="Samples">
<xsd:complexType>
<xsd:sequence>
<xsd:element type="Sample2Type" name="Sample2" minOccurs="0" maxOccurs="unbounded"/>
<xsd:element type="Sample1Type" name="Sample1" minOccurs="1" maxOccurs="1"/>
<xsd:element type="Sample2Type" name="Sample2" minOccurs="0" maxOccurs="unbounded"/>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
</xsd:schema>
OR even shorter for simple types:
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<xsd:element name="Samples">
<xsd:complexType>
<xsd:sequence>
<xsd:element type="xsd:string" name="Sample2" minOccurs="0" maxOccurs="unbounded"/>
<xsd:element type="xsd:boolean" name="Sample1" minOccurs="1" maxOccurs="1"/>
<xsd:element type="xsd:string" name="Sample2" minOccurs="0" maxOccurs="unbounded"/>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
</xsd:schema>
P.S.::
There are unfortunately no XSD elements like xsd:sequence, which will allow, what you ask.
What you want looks like xsd:all; however, since xsd:all only works for elements for which maxOccurs is 1, it will not work here. If you can combine choices and sequences to constrain your content, one way to go around duplication of definition (avoid defining twice) is to define Sample1 and Sample 2 as global elements and then ref them under your compositors. If defining global elements is not an option except for your root elements, then you could at least define the types globally - this way you maximize the reuse, and somewhat getting closer to your requirement "without defining twice"...

How to validate textfield element in xsd:schema

I am using xsd:schema which will be used to generated desired xml, I have a title field in xsd:schema.
I want to validate it from xsd:schema only that whenever user try to put values more than 10 characters, it will generate the error.
Below is the part of my xsd:schema
<xsd:sequence>
<xsd:element name="Title" minOccurs="0" maxOccurs="1" type="xsd:normalizedString"/>
<xsd:element name="City" minOccurs="0" maxOccurs="1" type="tcmi:SimpleLink">
<xsd:annotation>
<xsd:appinfo>
<tcm:linktype>ComponentLink</tcm:linktype>
<tcm:AllowMultimediaLinks>false</tcm:AllowMultimediaLinks>
<tcm:AllowedTargetSchemas>
<tcm:TargetSchema xlink:href="tcm:227-190428-8" xlink:title="City"/>
</tcm:AllowedTargetSchemas>
</xsd:appinfo>
</xsd:annotation>
</xsd:element>
<xsd:element name="FlightLinkText" minOccurs="0" maxOccurs="1" type="xsd:normalizedString"/>
</xsd:sequence>
I means that can we validate it from <xsd:element name="Title" minOccurs="0" maxOccurs="1" type="xsd:normalizedString"/>
Please suggest!
Have you tried something like:
<xsd:element name="Title" minOccurs="0" maxOccurs="1">
<xsd:simpleType>
<xsd:restriction base="xsd:normalizedString">
<xsd:maxLength value="10"/>
</xsd:restriction>
</xsd:simpleType>
</xsd:element>

Resources