XML-Binding (JAXB)
- Principle
- Compiling commands
- Example
- Other example
- Natural schema does not work
- Correction
-
Translating a schema into
a class system via the
xjc
compiler (from Java 6).
Using it with package javax.xml.bind
The idea is to postulate that types specified by XML Schemas can be
translated as types in the sense of Java, i.e. classes.
Suppose schema XS is translated into a system of Java classes JS.
The JAXB framexork then allows
- reading an XML file which is XS-compliant into a set of Java
objects, instances of JS (so-called unmarshalling process);
- executing arbitrary Java code on this set of objects
(modifying their state, deleting some and creating others);
- exporting the modified set of objects as a XS-compliant XML
file (so-called marshalling process).
-
- Command
$ xjc mySchema.xsd
will put the generated material into
a Java package called generated
- Command
$ xjc -p myPackage mySchema.xsd
will put the generated material into
a Java package called myPackage
-
We use a modified version of the Names
& Marks
#1 schema (Russian doll design) to avoid an ambiguity of the name
List
.
It translates as a
Java package with 2 class files :
Studentlist
- observe the Java annotation
@XmlRootElement(name =
"studentlist")
on public class Studentlist {...
- note the member class :
public static class
Student
{...
(which compiles as Studentist$Student
)
ObjectFactory
which is for
administration.
Usage :
- reading a list
ReadList
,
jfp$ java generated/ReadList NM1.xml
Hélène has mark : 12
André has mark : 15
Noémie has mark : 17
François has mark : 9
Jules has mark : 17
- creating a list (from a text file or other)
CreateList
,
jfp$ java generated/CreateList
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<studentlist>
<student name="Hélène" mark="12"/>
<student name="André" mark="15"/>
<student name="Noémie" mark="17"/>
<student name="François" mark="9"/>
</studentlist>
- modifying a list
ModifList
,
jfp$ java generated/ModifList NM1.xml Max 13
NNM1.xml
Fatto !
macbookprojf:JAXB jfp$ cat NNM1.xml
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<studentlist>
<student name="Hélène" mark="12"/>
<student name="André" mark="15"/>
<student name="Noémie" mark="17"/>
<student name="François" mark="9"/>
<student name="Jules" mark="17"/>
<student name="Max" mark="13"/>
</studentlist>
-
-
Modified schema Names &
Marks
#1 (with 3 types declared as separate entities) translates as a
Java package with 3 classes
ListType
corresponding to <xsd:complexType
name="listType">
StudType
corresponding to <xsd:complexType
name="studType">
ObjectFactory
which is for
administration.
Note that classes are associated with <xsd:complexType>
,
and that <xsd:simpleType name="markOver20">
has no
counterpart on the Java side.
This was to be expected since Java (for very good reasons) has no way
to treat an interval of integers as a type.
However, there is no class with annotation @XmlRootElement(name
=
"studentlist")
, and no class
which will prevent the result of the unmarshalling process to be cast
as ListType
.
Exception in thread "main" java.lang.ClassCastException:
javax.xml.bind.JAXBElement cannot be cast to other.ListType
-
The cause of the above failure is that, for JAXB's taste, type
listType
is not linked closely enough to our root element studentlist
.
Replace the "loosely coupled" declarations
<xsd:element name="studentlist" type="listType"/>
<xsd:complexType name="listType">
<xsd:choice>
<xsd:element name="student"
type="studType" minOccurs="0" maxOccurs="unbounded"/>
</xsd:choice>
</xsd:complexType>
by a single one
<xsd:element name="studentlist">
<xsd:complexType>
<xsd:choice>
<xsd:element name="student"
type="studType" minOccurs="0" maxOccurs="unbounded"/>
</xsd:choice>
</xsd:complexType>
</xsd:element>
and leave the rest of the schema unchanged.
This compiles into 3 classes
Studentlist
corresponding to our top element <xsd:element name="studentlist">
StudType
corresponding to <xsd:complexType
name="studType">
,
which plays the role of the local class Studentist$Student
in the Russian Doll design;
ObjectFactory
for
administration.
which work as expected (see e.g. ReadList
).