XML Schema
We will map our object model to the following XML schema that contains a choice structure. In this XML schema the choice structure means that after the name element, one of the following elements may occur: address, phone-number, or note.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
|
<?
xml
version
=
"1.0"
encoding
=
"UTF-8"
?>
<
xsd:element
name
=
"customer"
type
=
"customer"
/>
<
xsd:complexType
name
=
"customer"
>
<
xsd:sequence
>
<
xsd:element
name
=
"name"
type
=
"xsd:string"
minOccurs
=
"0"
/>
<
xsd:choice
>
<
xsd:element
name
=
"address"
type
=
"address"
/>
<
xsd:element
name
=
"phone-number"
type
=
"phoneNumber"
/>
<
xsd:element
name
=
"note"
type
=
"xsd:string"
/>
</
xsd:choice
>
</
xsd:sequence
>
</
xsd:complexType
>
<
xsd:complexType
name
=
"address"
>
<
xsd:sequence
>
<
xsd:element
name
=
"city"
type
=
"xsd:string"
minOccurs
=
"0"
/>
<
xsd:element
name
=
"street"
type
=
"xsd:string"
minOccurs
=
"0"
/>
</
xsd:sequence
>
</
xsd:complexType
>
<
xsd:complexType
name
=
"phoneNumber"
>
<
xsd:simpleContent
>
<
xsd:extension
base
=
"xsd:string"
>
<
xsd:attribute
name
=
"type"
type
=
"xsd:string"
/>
</
xsd:extension
>
</
xsd:simpleContent
>
</
xsd:complexType
>
</
xsd:schema
>
|
Java Model
We will use the following domain model for this example. The model represents information about a customer.
We will use the @XmlElements annotation to map to the choice structure. Inside @XmlElements are multiple @XmlElement annotations that link a element with a given name and namespace to a class. During a marshal operation the type of object held by the "contactInfo" property will dictate the element produced, and during an unmarshal operation the element information will dictate what type of object is instantiated.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
package
blog.choice;
import
javax.xml.bind.annotation.*;
@XmlAccessorType
(XmlAccessType.FIELD)
public
class
Customer {
private
String name;
@XmlElements
(value = {
@XmlElement
(name=
"address"
,
type=Address.
class
),
@XmlElement
(name=
"phone-number"
,
type=PhoneNumber.
class
),
@XmlElement
(name=
"note"
,
type=String.
class
)
})
private
Object contactInfo;
}
|
Address
1
2
3
4
5
6
7
8
9
|
package
blog.choice;
public
class
Address {
private
String street;
private
String city;
}
|
PhoneNumber
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
package
blog.choice;
import
javax.xml.bind.annotation.*;
@XmlAccessorType
(XmlAccessType.FIELD)
public
class
PhoneNumber {
@XmlAttribute
private
String type;
@XmlValue
private
String number;
}
|
First we will set an instance of Address on the "contactInfo" property:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
package
blog.choice;
import
javax.xml.bind.*;
public
class
DemoWithAddress {
public
static
void
main(String[] args)
throws
Exception {
Customer customer =
new
Customer();
customer.setName(
"Jane Doe"
);
Address address =
new
Address();
address.setStreet(
"1 A Street"
);
address.setCity(
"Any Town"
);
customer.setContactInfo(address);
JAXBContext jc = JAXBContext.newInstance(Customer.
class
, PhoneNumber.
class
, Address.
class
);
Marshaller marshaller = jc.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT,
true
);
marshaller.marshal(customer, System.out);
}
}
|
This will result in the following XML:
1
2
3
4
5
6
7
|
<
customer
>
<
name
>Jane Doe</
name
>
<
address
>
<
city
>Any Town</
city
>
<
street
>1 A Street</
street
>
</
address
>
</
customer
>
|
Next we will set an instance of PhoneNumber on the "contactInfo" property :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
package
blog.choice;
import
javax.xml.bind.*;
public
class
DemoWithPhoneNumber {
public
static
void
main(String[] args)
throws
Exception {
Customer customer =
new
Customer();
customer.setName(
"Jane Doe"
);
PhoneNumber phoneNumber =
new
PhoneNumber();
phoneNumber.setType(
"work"
);
phoneNumber.setNumber(
"555-1111"
);
customer.setContactInfo(phoneNumber);
JAXBContext jc = JAXBContext.newInstance(Customer.
class
, PhoneNumber.
class
, Address.
class
);
Marshaller marshaller = jc.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT,
true
);
marshaller.marshal(customer, System.out);
}
}
|
This will result in the following XML:
1
2
3
4
|
<
customer
>
<
name
>Jane Doe</
name
>
<
phone-number
type
=
"work"
>555-1111</
phone-number
>
</
customer
>
|
Finally we will set an instance of String on the "contactInfo" property:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
package
blog.choice;
import
javax.xml.bind.*;
public
class
DemoWithString {
public
static
void
main(String[] args)
throws
Exception {
Customer customer =
new
Customer();
customer.setName(
"Jane Doe"
);
customer.setContactInfo(
"jane.doe@example.com"
);
JAXBContext jc = JAXBContext.newInstance(Customer.
class
, PhoneNumber.
class
, Address.
class
);
Marshaller marshaller = jc.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT,
true
);
marshaller.marshal(customer, System.out);
}
}
|
This will result in the following XML:
1
2
3
4
|
<
customer
>
<
name
>Jane Doe</
name
>
<
note
>jane.doe@example.com</
note
>
</
customer
>
|