简述
不过在展开 JAXB 的讨论之前,我要简要地回顾一下本系列 上一篇文章中所提到的概念。其中的重要定义有:
解组:把 XML 数据转化成 Java 类(或者多个类)的过程。
编组:把 Java 数据转化成 XML 文档的过程(恰恰与解组相反)。
语义等价:基于 XML 规则的相等。即使两个文档 看起来不同,但在语义上可能是等价的,参见上一篇文章中的例子。
往返:从 XML 文档到 Java 代码然后再回到 XML 的整个过程。有效的往返保证输入和输出文档是相同的(语义等价)。
本文中将不那么严格地使用这些术语,一定要真正掌握每个概念的含义。
还应该明白,本文以及后面的几篇文章中,重点不一定是讨论基本的功能,而使这种功能的实现。煤中数据绑定工具包都能编组和解组数据。但是许多工具包不那么严格地执行这项任务,结果危害了往返的语义等价性。实现中的瑕疵(或者实现的功能不完整)是本系列中开始几篇文章的重点,因此我要用几篇文章来说明工具包的基本用法就不奇怪了,如果不知道它是否 真正有效, 使用一个工具包又有什么意义呢?
最后,我假设您已经安装并运行了 JAXB。您可以在 developerWorks上找到详细描述安装过程的大量文章,而且有了新的 Sun Java Web Services Developer Toolkit,安装非常简单。安装好工具包并设置正确的类路径,就万事俱备了。
生成类
使用 JAXB 进行之前,首先要生成表示 XML 数据的 Java 类。这些例子中将使用一个非常简单的 XML 文档,如清单 1 所示。这是一份吉他的简单列表,吉他是我的爱好之一。
清单 1. 简单的 XML 文档:吉他列表
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
28
29
30
31
32
|
<
guitars
>
<
guitar
id
=
"10021"
>
<
builder
luthier
=
"true"
>Ryan</
builder
>
<
model
>Mission Grand Concert</
model
>
<
back-sides
>Brazilian Rosewood</
back-sides
>
<
top
>Adirondack Spruce</
top
>
<
notes
>
<![CDATA[
Just unbelievable... this guitar has all the tone &
resonance you could ever want. I mean, <<WOW!!!>> This
is a lifetime guitar.
]]>
</
notes
>
</
guitar
>
<
guitar
id
=
"0923"
>
<
builder
smallShop
=
"true"
>Bourgeois</
builder
>
<
model
>OMC</
model
>
<
back-sides
>Bubinga</
back-sides
>
<
top
>Adirondack Spruce</
top
>
</
guitar
>
<
guitar
id
=
"11091"
>
<
builder
>Martin & Company</
builder
>
<
model
>OM-28VR</
model
>
<
back-sides
>Indian Rosewood</
back-sides
>
<
top
bearclaw
=
"true"
>Sitka Spruce</
top
>
<
notes
>It's certainly true that Martin isn't the only game in town anymore.
Still, the OM-28VR is one of their best models... and this one
has some fabulous bearclaw to boot. Nice specimen of a
still-important guitar manufacturer.
</
notes
>
</
guitar
>
</
guitars
>
|
使用 JAXB 时还需要一个 XML Schema 以生成类和数据结构。 清单 1的 XML Schema 如清单 2 所示。
清单 2. 清单 1 的 XML Schema
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
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
|
<?
xml
version
=
"1.0"
encoding
=
"UTF-8"
?>
elementFormDefault
=
"qualified"
>
<
xs:element
name
=
"back-sides"
type
=
"xs:string"
/>
<
xs:element
name
=
"builder"
>
<
xs:complexType
>
<
xs:simpleContent
>
<
xs:extension
base
=
"xs:string"
>
<
xs:attribute
name
=
"luthier"
default
=
"false"
>
<
xs:simpleType
>
<
xs:restriction
base
=
"xs:NMTOKEN"
>
<
xs:enumeration
value
=
"true"
/>
<
xs:enumeration
value
=
"false"
/>
</
xs:restriction
>
</
xs:simpleType
>
</
xs:attribute
>
<
xs:attribute
name
=
"smallShop"
default
=
"false"
>
<
xs:simpleType
>
<
xs:restriction
base
=
"xs:NMTOKEN"
>
<
xs:enumeration
value
=
"true"
/>
<
xs:enumeration
value
=
"false"
/>
</
xs:restriction
>
</
xs:simpleType
>
</
xs:attribute
>
</
xs:extension
>
</
xs:simpleContent
>
</
xs:complexType
>
</
xs:element
>
<
xs:element
name
=
"guitar"
>
<
xs:complexType
>
<
xs:sequence
>
<
xs:element
ref
=
"builder"
/>
<
xs:element
ref
=
"model"
/>
<
xs:element
ref
=
"back-sides"
/>
<
xs:element
ref
=
"top"
/>
<
xs:element
ref
=
"notes"
minOccurs
=
"0"
/>
</
xs:sequence
>
<
xs:attribute
name
=
"id"
type
=
"xs:string"
use
=
"required"
/>
</
xs:complexType
>
</
xs:element
>
<
xs:element
name
=
"guitars"
>
<
xs:complexType
>
<
xs:sequence
>
<
xs:element
ref
=
"guitar"
maxOccurs
=
"unbounded"
/>
</
xs:sequence
>
</
xs:complexType
>
</
xs:element
>
<
xs:element
name
=
"model"
type
=
"xs:string"
/>
<
xs:element
name
=
"notes"
type
=
"xs:string"
/>
<
xs:element
name
=
"top"
>
<
xs:complexType
>
<
xs:simpleContent
>
<
xs:extension
base
=
"xs:string"
>
<
xs:attribute
name
=
"bearclaw"
default
=
"false"
>
<
xs:simpleType
>
<
xs:restriction
base
=
"xs:NMTOKEN"
>
<
xs:enumeration
value
=
"true"
/>
<
xs:enumeration
value
=
"false"
/>
</
xs:restriction
>
</
xs:simpleType
>
</
xs:attribute
>
</
xs:extension
>
</
xs:simpleContent
>
</
xs:complexType
>
</
xs:element
>
</
xs:schema
>
|