使用JAXB将XML Schema绑定到Java类

29 篇文章 1 订阅

http://blog.csdn.net/zsyspace/article/details/1786079

Java Architecture for XML Binding (JAXB) 是一项可以根据XML 模式产生Java类的Java技术。该过程中,JAXB也提供了将XML实例文档反编组到Java内容树的方法,并能将Java内容树编组回XML实例文档。从另一方面来讲,JAXB提供了快速而简便的方法将XML模式绑定到Java表示,从而使得Java开发者在Java应用程序中能方便地结合XML数据和处理函数。

这意味着你不需要处理甚至不需要知道XML编程技巧就能在Java应用程序中利用平台核心XML数据的灵活性。而且,可以充分利用XML的优势而不用依赖于复杂的XML处理模型如SAX或DOM。JAXB 隐藏了细节并且取消了SAX和DOM中没用的关系——生成的JAXB类仅描述原始模型中定义的关系。其结果是结合了高度可移植Java代码的高度可移植的XML数据,其中这些代码可用来创建灵活、轻便的应用程序和Web服务。

本章介绍了JAXB体系结构、函数和核心概念。在学习第十章之前必须先阅读本章。第十章给出了示例代码和逐步使用JAXB的过程。

JAXB 体系结构

本节主要讨论JAXB处理模型中的组件和交互。在给出了总的概述之后,本节将详细讨论核心的JAXB特性。本节中的主题主要包括:

体系结构概述

图 9-1 给出了构成JAXB实现的组件。

图 9-1 JAXB体系结构概述

如图9-1所示,JAXB实现包含下列八个核心组件:

9-1 JAXB实现中的核心组件

组件

描述

XML Schema

XML模式使用XML语法描述XML文档中元素、属性和实体之间的关系。XML模式的目标是定义一个XML文档类,该类必须坚持特定的结构规则和数据约束。例如你可能希望给面向章的书、在线采购系统或个人数据库定义不同的模式。在JAXB上下文中,将包含数据的受到XML模式约束的XML文档叫做文档实例,并且将文档实例中的结构和数据叫做内容树

Binding
Declarations

默认情况下,JAXB绑定编译器根据JAXB规范第5节“将XML Schema绑定到Java表示”中定义的规则将Java类和包绑定到原始XML模式。多数情况下,利用默认的规则已经能够从大量的模式中产生一组强壮的模式派生类。但是,有的时候,默认的绑定规则就不够用了。JAXB支持通过绑定声明自定义或覆盖默认的绑定规则。这些绑定声明或者是内部源模式的注释或者是传递给JAXB绑定编译器的外部绑定自定义文件中的语句。注意自定义的JAXB绑定声明也允许摆脱XML模式中特定于XML的束缚,来自定义生成的JAXB类,以包含特定于Java的改进,如类和包名映射

Binding
Compiler

JAXB绑定编译器是JAXB处理模型的核心。它的功能是将源XML模式转换或绑定到Java编程语言中的一组JAXB内容类。基本上,可以通过将一个XML模式 (可以选择使用自定义绑定声明)用作输入来运行JAXB绑定编译器。绑定编译器产生Java类,这些Java类映射到了源XML 模式中的约束条件

Binding
Framework
Implementation

JAXB绑定框架实现是运行时API,它提供了反编组、编组和验证Java应用程序中的XML内容的接口。绑定框架包括javax.xml.bind包中的接口

Schema-Derived
Classes

这些是JAXB编译器产生的模式派生类。根据输入的模式将采用不同的类

Java
Application

JAXB上下文中,Java应用程序是客户端应用程序,它使用JAXB绑定框架来反编组XML数据,验证并修改Java内容对象,并将Java内容编组成XML数据。特别是,JAXB绑定框架包装在一个能提供UI功能、XML转换功能、数据处理或其他所需要的功能的大型Java应用程序中

XML Input
Documents

这是反编组出来用作JAXB绑定框架输入的XML内容——即XML实例文档,从这里将产生内容树形式的Java表示。实际上,术语“文档”不再是传统意义上的文档了,因为XML实例文档不一定要是形式完整的、自立的文档文件;相反它具有流的形式,这些流可以是应用程序之间传递的数据、数据库字段集合、XML信息集合,其中信息块包含了描述它们在模式结构中的位置的足够信息。

 

JAXB中,反编组过程支持根据源模式定义的约束验证XML输入文档。然而该验证过程是可选的,在某些情况下你可能通过其他途径知道输入文档是有效的,出于对性能的考虑你可能选择在反编组过程中跳过验证。但是,无论在哪种情况下,反编组之前(通过第三方应用程序)或之后验证都很重要,这是因为它确保了关于源模式编组过程中产生的XML文档也是有效的。在本章的后面部分将详细介绍验证

XML Output
Documents

这是编组到XML文档的XML内容。在JAXB编组包括解析XML内容对象树并写出一个XML文档,该文档是原始XML文档的精确表示并且相对于原始模式来说是有效的。JAXB能够将XML数据编组成XML 文档、SAX内容处理程序和DOM节点。

JAXB绑定过程

图9-2显示了JAXB的绑定过程。

Steps in the JAXB Binding Process

图 9-2 JAXB绑定过程步骤

JAXB数据绑定过程的常用步骤是:

1.       生成类。将XML模式放入JAXB绑定编译器,以产生基于该模式的JAXB类。

2.       编译类。必须编译所有生成的类、源文件和应用程序代码。

3.       反编组。JAXB绑定框架反编组根据原始模式中的约束编写的XML文档。注意JAXB也支持反编组来自除了文件/文档之外XML数据,如DOM节点、字符串缓冲、SAX Source等等。

4.       生成内容树。反编组过程产生从生成的JAXB类实例化而来的数据对象内容树,该内容树代表了源XML文档的结构和内容。

5.       验证(可选)反编组过程中,可以在生成内容树之前验证源XML文档。注意,如果在第6步中修改内容树,下面,你也能使用JAXB验证操作在将内容编组到XML文档之前验证变化。

6.       处理内容。客户端应用程序通过绑定编译器产生的接口方法可以修改Java内容树表示的XML数据。

7.       编组。将处理过的内容树编组到一个或多个XML输出文档中。在编组之前要验证内容。

总而言之,使用JAXB涉及到两个独立的活动集:

  • 根据源模式生成并编译JAXB类,并且建立一个实现这些类的应用程序。
  • 在JAXB绑定框架中运行应用程序,以反编组、处理、验证和编组XML内容。

通常分时间分阶段执行这两个步骤。典型地,例如,需要在应用程序开发阶段生成并编译JAXB类,并且建立绑定实现,接着是部署阶段,在该阶段使用生成的JAXB类在“现场”产品环境中处理XML内容。


注意:反编组不是创建内容树的唯一的方法。模式派生的内容类通过直接调用合适的工厂方法也支持按计划构建内容树。一旦创建了,任何时候都可以重新验证内容树的一部分或全部。查看示例应用程序 3 中的使用ObjectFactory 类直接给内容树添加内容的例子。


JAXB绑定框架

JAXB绑定框架由三个Java包实现:

  • javax.xml.bind 包定义直接和内容类一起使用的抽象类和接口。

javax.xml.bind 包定义UnmarshallerValidatorMarshaller 类,它们是提供各自操作的辅助对象。

JAXBContext 类是Java应用程序到JAXB框架的入口点。JAXBContext 实例为反编组、编组和验证操作使用的JAXB实现将XML元素名绑定到Java内容接口。

javax.xml.bind 包也定义了编组或反编组错误出现时、违反约束时及出现其他类型的错误时使用的丰富的验证事件和异常类的层次结构。

  • javax.xml.bind.util 包包含工具类,客户端应用程序可以使用它们来管理编组、反编组和验证事件。
  • javax.xml.bind.helper 包为一些javax.xml.bind 接口提供了部分默认的实现。JAXB的实现能够扩展这些类并且实现抽象方法。使用JAXB体系结构的应用程序不能直接使用这些API。

下面将详细介绍JAXB绑定框架中的主要的包javax.bind.xml

关于javax.xml.bind的更多信息

主要绑定框架包javax.xml.bind提供的三个核心功能是编组、反编组和验证。到绑定框架的主要的客户端入口点是JAXBContext 类。

JAXBContext 提供了一个抽象,该抽象可以管理实现反编组、编组和验证操作必要的XML/Java绑定信息。客户端应用程序通过newInstance(contextPath)方法得到该类的新实例。例如:

JAXBContext jc = JAXBContext.newInstance( 
"com.acme.foo:com.acme.bar" ); 

contextPath 参数包含一个Java包名,这些包包含模式派生的接口—特别是JAXB绑定编译器产生的接口。该参数值初始化JAXBContext 对象,使得它能够管理模式派生的接口。为此目的,JAXB提供程序实现必须提供一个包含下列特征的实现类:

public static JAXBContext createContext( String contextPath, 
ClassLoader classLoader ) 
      throws JAXBException; 

注意:在每个包含模式派生类的包中,JAXB提供程序实现必须生成一个jaxb.properties 文件。该属性文件必须包含一个叫做javax.xml.bind.context.factory 的属性,它的值是实现createContext API的类的名字。

不一定要将提供程序提供的类分配给javax.xml.bind.JAXBContext,它只是必须提供一个实现 createContext API的类。允许指定多个Java包,JAXBContext 实例允许同时管理多个模式。


关于反编组的更多信息

javax.xml.bind 包中的Unmarshaller 类使得客户端应用程序能够将XML数据转换成Java内容对象树。模式的unmarshal 方法(在命名空间内)允许将模式中声明的任何全局XML元素反编组成实例文档的根。JAXBContext 对象允许在一组模式内合并全局元素(列在contextPath)。由于模式集中的每个模式属于不同的命名空间,将模式统一到反编组上下文中是独立于命名空间的。这意味着客户端应用程序能够反编组contextPath 中列出的任何模式的实例XML文档。例如:

JAXBContext jc = JAXBContext.newInstance(
  "com.acme.foo:com.acme.bar" );
 
Unmarshaller u = jc.createUnmarshaller();
 
FooObject fooObj = 
  (FooObject)u.unmarshal( new File( "foo.xml" ) ); // ok
 
BarObject barObj = 
  (BarObject)u.unmarshal( new File( "bar.xml" ) ); // ok
 
BazObject bazObj = 
  (BazObject)u.unmarshal( new File( "baz.xml" ) ); 
  // error, "com.acme.baz" not in contextPath 

客户端应用程序也能明显地生成Java内容树而不是反编组现有XML数据。这样做,应用程序必须能够存取并了解contextPath 中的每个Java包中模式派生的ObjectFactory 类。对于每个模式派生Java类,将有一个静态工厂方法能产生该类型的对象。例如,假设编译了模式之后,得到一个包含PurchaseOrder 模式派生接口的包com.acme.foo 。要创建这类对象,客户端应用程序将使用下列工厂方法:

ObjectFactory objFactory = new ObjectFactory();
 
com.acme.foo.PurchaseOrder po =
  objFactory.createPurchaseOrder(); 

注意:由于当contextPath 上有多个包时,会产生多个ObjectFactory 类,所以如果你有多个contextPath上的包,在引用某个包中的ObjectFactory 类时,必须使用完整的包名。


一旦客户端应用程序有模式派生对象的实例,它就能使用赋值方法来设置它的内容。


注意:JAXB 提供程序实现必须在每个包中生成一个类,这些包包含ObjectFactory 包的必要的对象工厂方法和newInstance( javaContentInterface ) 方法。


关于编组的更多信息

javax.xml.bind 包中的Marshaller 类使得客户端应用程序能够将Java内容树转换成XML数据。编组一个使用工厂方法人为创建的内容树和反编组操作得到的内容树之间没有什么区别。客户端能够将Java内容树编组回到java.io.OutputStreamjava.io.WriterXML数据中。编组过程能够在注册的ContentHandler 中生成SAX2 事件流或生成DOM Node 对象。

下面是一个简单的例子,它反编组一个XML文档,然后在将它编组回去:

JAXBContext jc = JAXBContext.newInstance( "com.acme.foo" );
 
// unmarshal from foo.xml
Unmarshaller u = jc.createUnmarshaller();
FooObject fooObj = 
  (FooObject)u.unmarshal( new File( "foo.xml" ) );
 
// marshal to System.out
Marshaller m = jc.createMarshaller();
m.marshal( fooObj, System.out ); 

默认情况下,在java.io.OutputStream java.io.Writer中生成XML数据时,Marshaller使用UTF-8 编码。使用setProperty API 改变编组操作中输出的编码。客户端应用程序提供W3C XML 1.0 推荐中定义的有效的字符编码名(http://www.w3.org/TR/2000/REC-xml-20001006#charencoding) 并且你的Java平台支持它。

在调用编组API之前,不要求客户端应用程序验证Java内容树。同样,也不要求根据源模式验证Java内容树以便将它编组回XML数据。不同的JAXB提供程序支持编组不同层的无效Java内容树,然而,所有的JAXB提供程序必须能够将有效的内容树编组成XML数据。当JAXB提供程序由于无效的内容而不能完成编组操作时必须抛出MarshalException 。一些JAXB提供程序将完全支持编组无效内容,而其他一些将在遇到第一个验证错误后就失效。

表 9-2 列出了Marshaller 类支持的属性

9-2   Marshaller 属性

属性

描述

jaxb.encoding

值必须是java.lang.String;这是编组XML数据时使用的输出编码。默认情况下,如果没有指定它的属性,Marshaller将使用"UTF-8"

jaxb.formatted.output

值必须是java.lang.Boolean。它控制Marshaller是否使用行分隔和缩进格式化结果XML数据。如果它的值为true表示易读缩进的XML数据,如果值为false表示未格式化的XML数据。如果没有指定该属性,Marshaller的默认值为false (unformatted)

jaxb.schemaLocation

值必须是java.lang.String;它允许客户端应用程序指定生成的XML数据中的xsi:schemaLocation属性。W3C XML Schema部分0:入门的第5.6节中通过一种易于理解的、非标准的形式介绍了schemaLocation属性值的格式,并且在W3C XML Schema Part 1:结构的第2.6节中规定了该属性值的格式

jaxb.noNamespaceSchemaLocation

值必须是java.lang.String;允许客户端应用程序指定生成的XML数据中的xsi:noNamespaceSchemaLocation属性

关于验证的更多信息

javax.xml.bind 包中的Validator 类主要用来在运行时控制对内容树的验证。当反编组过程结合了验证,并且验证成功,没有产生任何验证错误,那么就能确保输出的文档和结果内容树是有效的。相对比,编组过程中并不进行验证。如果仅仅编组有效的内容树,这就能保证相对于源模式来说,生成的XML文档总是有效的。

一些XML解析器如SAX和DOM允许取消模式验证功能,并且在一些情况下,为了提高处理速度并且/或者为了处理包含无效或不完整的内容的文档,你可能希望取消模式验证。通过在能使用JAXB的应用程序中选泽的异常处理程序,JAXB支持这些处理方案。总的说来,如果一个JAXB实现不能确切完成反编组或编组,它将抛出一个异常,终止处理。


注意:Validator 类负责管理On-Demand验证(如下所示)。Unmarshaller 类负责管理反编组操作中的 Unmarshal-Time 验证。虽然没有正式的方法能够在编组操作中启动验证,Marshaller 可以监测错误,将它报告给它上面注册的ValidationEventHandler


JAXB客户端可以实现两类验证:

  • Unmarshal-Time 验证 使得客户端应用程序能够接收将XML数据反编组到Java内容树时监测到的验证错误消息和警告,并且跟验证的其他类型完全正交。使用Unmarshaller.setValidating方法来启动或终止它。所有的JAXB提供程序都要支持该操作。
  • On-Demand 验证 使得客户端应用程序能够接收Java内容树中监测到的验证错误和警告。这点上,客户端应用程序能够在Java内容树(或者它的任何子树)上调用Validator.validate 方法。所有的JAXB提供程序都要支持该操作。

如果客户端应用程序没有在调用验证、反编组或编组方法之前就在它的ValidatorUnmarshallerMarshaller 上设置事件处理程序,那么默认的事件处理程序将接收遇到的任何错误通知。在遇到第一个错误或致命错误后,默认的事件处理程序将挂起当前操作 (但是在接收到警告后将继续该操作)

有三种方法能够处理反编组、验证和编组操作过程中遇到的事件:

  • 使用默认的事件处理程序。

如果没有通过ValidatorUnmarshallerMarshaller上的setEventHandler API设置事件处理程序,将会使用默认的事件处理程序。

  • 实现并注册一个自定义的事件处理程序。

需要复杂的事件处理的客户端应用程序能够实现ValidationEventHandler 接口并使用Unmarshaller 和/或 Validator注册它。

  • 使用ValidationEventCollector 工具。

为了方便,提供一个特定的事件处理程序,该处理程序仅仅收集反编组、验证和编组操作中创建的ValidationEvent 对象,并且将它们作为java.util.Collection返回给客户端应用程序。

根据客户端应用程序的配置,使用不同的方法来处理验证事件。然而,在一些情况下,JAXB提供程序不能正确地监测并报告错误。在这些情况下,JAXB提供程序将ValidationEvent 的验证性设置成 FATAL_ERROR ,表明将终止反编组、验证和编组操作。在收到致命错误的通知后,默认的事件处理程序和ValidationEventCollector工具类必须终止处理。接收到致命错误的通知后,支持它们自己的ValidationEventHandler 客户端应用程序必须也终止处理。如果不终止处理,将会出现意想不到的情况。

XML Schema

由于XML模式是JAXB处理模型的一个重要的组件——并且由于其他数据绑定性能如JAXP使用DTD而不用模式——因此在这里了解一下XML模式的基本概念和它们的工作原理很有用。

XML Schema是描述XML文档中允许的元素、属性、实体和关系的强大的方法。DTD的一个更加强壮的选择,XML模式的目标是定义XML文档的类,该类必须遵守一组特定的结构和数据约束——也就是说,你可能希望为面向章的书、在线采购系统或个人数据库定义不同的模式。在JAXB上下文中,将包含受到XML模式约束的XML文档称作文档实例,并且将文档实例内部的结构和数据叫做内容树。


注意:实际上,术语“文档”并不总是精确的,因为XML实例文档不一定要是形式完整的、自立的文档文件;相反它具有流的形式,这些流可以是应用程序之间传递的数据、数据库字段集合、XML信息集合,其中信息块包含了描述它们在模式结构中的位置的足够信息。


下面的例子代码来自于W3C Schema 部分 0:入门(http://www.w3.org/TR/2001/REC-xmlschema-0-20010502/),显示了一个XML文档po.xml,是一个简单的购买订单。

<?xml version="1.0"?>

<purchaseOrder orderDate="1999-10-20">

  <shipTo country="US">

    <name>Alice Smith</name>

    <street>123 Maple Street</street>

    <city>Mill Valley</city>

    <state>CA</state>

    <zip>90952</zip>

  </shipTo>

  <billTo country="US">

    <name>Robert Smith</name>

    <street>8 Oak Avenue</street>

    <city>Old Town</city>

    <state>PA</state>

    <zip>95819</zip>

  </billTo>

<comment>Hurry, my lawn is going wild!</comment>

  <items>

    <item partNum="872-AA">

      <productName>Lawnmower</productName>

      <quantity>1</quantity>

      <USPrice>148.95</USPrice>

      <comment>Confirm this is electric</comment>

    </item>

    <item partNum="926-AA">

      <productName>Baby Monitor</productName>

      <quantity>1</quantity>

      <USPrice>39.98</USPrice>

      <shipDate>1999-05-21</shipDate>

    </item>

  </items>

</purchaseOrder>

根元素purchaseOrder包含子元素shipTo, billTocommentitems。除了comment之外的所有子元素包含其他子元素。树的叶子是子元素,如name, streetcitystate,它们不包含任何子元素。包含其他子元素或能接受属性的元素叫做复合类型。仅包含PCDATA并且没有子元素的元素叫做简单类型。

下面的采购模式中定义了po.xml中的复杂类型和一些简单类型。同样,该例子模式来自于W3C Schema 部分 0:入门(http://www.w3.org/TR/2001/REC-xmlschema-0-20010502/).

<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">

<xsd:element name="purchaseOrder" type="PurchaseOrderType"/>

<xsd:element name="comment" type="xsd:string"/>

<xsd:complexType name="PurchaseOrderType">

  <xsd:sequence>

    <xsd:element name="shipTo" type="USAddress"/>

    <xsd:element name="billTo" type="USAddress"/>

    <xsd:element ref="comment" minOccurs="0"/>

    <xsd:element name="items" type="Items"/>

  </xsd:sequence>

  <xsd:attribute name="orderDate" type="xsd:date"/>

</xsd:complexType>

 

<xsd:complexType name="USAddress">

  <xsd:sequence>

    <xsd:element name="name" type="xsd:string"/>

    <xsd:element name="street" type="xsd:string"/>

    <xsd:element name="city" type="xsd:string"/>

    <xsd:element name="state" type="xsd:string"/>

    <xsd:element name="zip" type="xsd:decimal"/>

  </xsd:sequence>

  <xsd:attribute name="country" type="xsd:NMTOKEN"

      fixed="US"/>

</xsd:complexType>

 

<xsd:complexType name="Items">

  <xsd:sequence>

    <xsd:element name="item" minOccurs="1"

              maxOccurs="unbounded">

      <xsd:complexType>

        <xsd:sequence>

          <xsd:element name="productName"

                    type="xsd:string"/>

          <xsd:element name="quantity">

            <xsd:simpleType>

              <xsd:restriction base="xsd:positiveInteger">

                <xsd:maxExclusive value="100"/>

              </xsd:restriction>

            </xsd:simpleType>

          </xsd:element>

          <xsd:element name="USPrice" type="xsd:decimal"/>

          <xsd:element ref="comment" minOccurs="0"/>

          <xsd:element name="shipDate" type="xsd:date"

                    minOccurs="0"/>

        </xsd:sequence>

        <xsd:attribute name="partNum" type="SKU"

                    use="required"/>

      </xsd:complexType>

    </xsd:element>

  </xsd:sequence>

</xsd:complexType>

 

<!-- Stock Keeping Unit, a code for identifying products -->

<xsd:simpleType name="SKU">

  <xsd:restriction base="xsd:string">

    <xsd:pattern value="/d{3}-[A-Z]{2}"/>

  </xsd:restriction>

</xsd:simpleType>

 

</xsd:schema>

在本例中,模式同DTD一样包含main或根schema元素和几个子元素elementcomplexTypesimpleType。和DTD不同,该模式也被指定成属性数据类型,如decimaldatefixedstring。模式也受到如pattern valueminOccurspositiveInteger的约束。在DTD中,只能指定文本数据(PCDATACDATA)的数据类型, XML模式支持更加复杂的文本和数值数据类型和约束,这些在Java语言中都有直接对应部分。

注意,本模式中的每个元素都有前缀xsd:,它和W3C XML Schema 命名空间相关。为此,命名空间声明,xmlns:xsd="http://www.w3.org/2001/XMLSchema", 声明的是schema元素的一个属性。

支持命名空间是XML Schema的另一个重要的特征,因为它为区分根据不同模式书写的元素提供了一个方法或有其他不同的用途,但是它们可能和文档中的其他元素有相同的名字。例如,假设你在你的模式中定义两个命名空间,一个是foo,另外一个是bar。结合两个XML 文档,一个来自于开账单数据库,另一个来自于运送数据库,每个都建立在不同的模式下。通过在模式中指定命名空间,你可以区分foo:addressbar:address

表示XML内容

本节介绍JAXB 如何将XML内容表示成Java对象。本节主题如下:

·   XML名字绑定到Java标识符

·   XML模式的Java表示

XML名字绑定到Java标识符

XML模式语言使用XML名字——与XML1.0(第二版本) (http://www.w3.org/XML/)中定义的用来标识模式组件的名字产品匹配的字符串。该字符串集合比有效的Java类、方法和约束标识符的集合大。要解决该差异,JAXB使用几个名字-映射算法。

JAXB名字-映射算法根据标准Java API设计指南将XML名字映射到Java标识符,生成保留了到相应模式连接的标识符,并且不太可能产生冲突。

参考第10章,查看如何改变默认XML名字映射。查看JAXB规范附录C中关于JAXB命名算法的完整细节。

XML模式的Java表示

JAXB支持组合Java包中生成的类和接口。一个包包括:

·   名字,直接来自于XML命名空间URI或由XML命名空间URI绑定自定义指定。

·   一组Java内容接口,表示模式中声明的内容模型。

·   一组Java元素接口,表示模式中出现的元素声明。

·   包含如下内容的一个ObjectFactory类:

o      每个Java内容接口的实例工厂方法和包中的Java元素接口,例如,给定一个叫做FooJava内容接口,取得的工厂方法是:

    public Foo createFoo() throws JAXBException; 

o      动态实例工厂分配器,创建指定的Java内容接口的一个实例,例如:

         public Object newInstance(Class javaContentInterface)
         throws JAXBException; 

o      getPropertysetProperty API ,它们允许操纵指定提供程序的属性。

·   typesafe 枚举类集合

·   javadoc

绑定XML Schema

本节介绍了JAXB使用的默认的XML-到-Java绑定。通过自定义绑定声明可以通过自定义的绑定声明全局覆盖或逐层覆盖所有这些绑定。本节主题如下:

·   简单类型定义

·   默认的数据类型绑定

·   默认的绑定规则摘要

查看JAXB 规范以获得JAXB绑定的完整信息。

简单类型定义

使用简单类型定义的模式组件通常和Java 属性绑定。由于有多种这类模式组件,下列Java特征属性(在模式组件中很常见)包括:

·   基本类型

·   集合类型,如果有的话

·   谓词

其他Java特征属性是使用simple 类型定义在模式组件中指定的。

默认的数据类型绑定

Java语言提供了比XML模式更加丰富的数据类型集。表 9-3 列出了XML数据类型到JAXB中的Java数据类型的映射。

9-3  XML模式内置数据类型的JAXB映射

XML Schema 类型

Java数据类型

xsd:string

java.lang.String

xsd:integer

java.math.BigInteger

xsd:int

int

xsd.long

long

xsd:short

short

xsd:decimal

java.math.BigDecimal

xsd:float

float

xsd:double

double

xsd:boolean

Boolean

xsd:byte

byte

xsd:Qname

javax.xml.namespace.QName

xsd:dateTime

java.util.Calendar

xsd:base64Binary

byte[]

xsd:hexBinary

byte[]

xsd:unsignedInt

long

xsd:unsignedShort

int

xsd:unsignedByte

short

xsd:time

Java.util.Calendar

xsd:date

Java.util.Calendar

xsd:anySimpleType

Java.lang.String

默认的绑定规则摘要

JAXB绑定模型遵守下列默认的绑定规则:

·   将下列内容绑定到Java包:

o      XML 命名空间URI

·   将下列XML模式组件绑定到Java内容接口:

o      命名的复杂类型

o      元素声明中匿名的内部类型定义

·   绑定到类型安全枚举类:

o      一个命名的简单类型定义,它有来自"xsd:NCName" 的基本类型,并且有枚举面。

·   将下列XML Schema组件绑定到Java Element接口:

o      Element 接口的全局元素声明

o      能够插入到全局内容列表的本地元素声明

·   绑定到Java属性:

o      使用的属性

o      元素引用或本地元素声明的术语微粒

·   将重复出现和复杂的类型定义的模型组和混合的{content type}绑定到:

o      通用内容属性;具有Java实例表示元素信息项和字符数据项的列表内容属性

自定义JAXB绑定

使用自定义的绑定声明可以在全局范围或逐层地覆盖默认的JAXB绑定。如前面所介绍的,JAXB 使用默认的绑定规则,可以通过下面两种方法可以自定义这些绑定规则:

·   XML模式的内部注释

·   传递给JAXB绑定编译器的外部绑定自定义文件中的声明

自定义JAXB绑定声明也能不受XML schema中的XML规范约束自定义生成的JAXB类,让它包括特定于Java改进,如类和包名映射。

你不需要为模式中的每个声明提供一个绑定指令来生成Java类。例如,绑定编译器使用通用的名字影射算法将XML名字绑定到Java编程语言能够接受的名字。然而,如果在类中想要使用不同的名字模式,你可以明确自定义绑定声明让绑定编译器生成不同的名字。在绑定声明中可以进行许多其他自定义,包括:

·   命名包、衍生类和方法

·   衍生类中的方法分配类型

·   选择将哪个元素绑定到类

·   确定如何将属性和元素声明绑定到适当内容类的属性

·   选择每个属性值或内容规范的类型


注意: 依赖于默认的JAXB绑定行为而不是为Java表示的每个XML Schema组件作出绑定声明使得它能够方便地跟上源模式中的变化。在多数情况下, 默认的规则非常强壮,所以不需要任何自定义的绑定声明就能产生可用的绑定。


第10章中给出了自定义JAXB绑定的代码例子。

作用域

当在绑定声明中定义自定义值时,就涉及到作用域。自定义值的作用域就是应用它的模式元素集合。如果将一个自定义值应用到一个模式元素,那么该模式元素就在自定义值的作用域内。

表 9-4 列出了自定义的绑定的四个作用域。

9-4 自定义绑定的作用域

作用域

描述

Global

<globalBindings>中定义的自定义值具有全局作用域。全局作用域覆盖了源模式中的所有模式元素和(递归的)源模式中包括或导入的任何模式

Schema

<schemaBindings>中定义的自定义值具有模式作用域。模式作用域覆盖了模式的目标命名空间的所有模式元素

Definition

类型定义的绑定声明中的自定义值和全局声明具有定义作用域。定义作用域覆盖了引用类型定义或全局声明的所有模式元素

Component

如果自定义值仅应用到绑定声明注释的模式元素,绑定声明中的自定义值具有组件作用域

作用域继承

不同的作用域形成了一个分类系统。该分类系统定义了自定义值的继承和覆盖语义。一个作用域内的自定义值被另一个作用域的绑定声明继承使用,下面是继承的层次关系:

·   模式作用域内的模式元素继承全局作用域内定义的自定义值。

·   定义作用域内的模式元素继承模式或全局作用域内定义的自定义值。

·   组件作用域内的模式元素继承定义、模式或全局作用域内定义的自定义值。

相似的,一个作用域内的自定义值能够覆盖继承自另一个作用域的自定义值,如下所示:

·   模式作用域内的值覆盖继承自全局作用域的值。

·   定义作用域内的值覆盖继承自模式作用域或全局作用域的值。

·   组件作用域的值覆盖继承自定义、模式或全局作用域的值。 

 

 

==============================

JAXB生成一个XML文档

开发者在线 Builder.com.cn 更新时间:2008-04-14

本文关键词:文档 xml JAXB JAVA

 一个XML 模式(Schema)XML语法表达了一个XML文档的结构。J2EE的开发者也许会需要一个符合XML模式的XML文档。Java XML绑定架构(JAXB)提供了一个绑定编译器,xjc,来从一个XML模式中生成Java类。用JAXBxjc生成的Java类代表了在XML模式中不同的元素和复杂类型(complexType)。(一个复杂类型通过指定属性和元素内的元素来提供对一个元素的限定)。一个符合XML模式的XML文档可以从这些Java类中构建出来。

      在这篇教程中,作者使用了JAXB用来从一个XML模式中生成Java类。这些Java类将会生成一个范例XML文档。这篇文章由以下几个部份组成:

1.预设置
2.
概述
3.
XMl模式中生成Java
4.
Java类中生成一个XML文档

      预设置

      为了用JAXB从一个XML模式中生成Java类,JAXB API类库和xjc工具应该存在CLASSPATH环境变量中。将Java Web服务开发包 (JWSDP) 1.5装入一个安装目录中。将下列的.jar文件加入CLASSPATH环境变量中。

·<JWSDP>/jaxb/lib/jaxb-api.jar
·<JWSDP>/jaxb/lib/jaxb-impl.jar
·<JWSDP>/jaxb/lib/jaxb-libs.jar
·<JWSDP>/jaxb/lib/jaxb-xjc.jar
·<JWSDP>/jwsdp-shared/lib/namespace.jar
·<JWSDP>/jwsdp-shared/lib/jax-qname.jar
·<JWSDP>/jwsdp-shared/lib/relaxngDatatype.jar

      <JWSDP>Java Web服务开发包1.5的安装目录。把<JWSDP>/jaxb/bin加入PATH环境变量中。<JWSDP>/jaxb/bin目录中包含了xjc编译器。把<JWSDP>/jwsdp-shared/bin目录加入到PATH环境变量中。<JWSDP>/jwsdp-shared/bin目录中包含了setenv的批处理文件,它设置了JAVA_HOME, ANT_HOMEJWSDP_HOME这几个环境变量。

       概述

      JAXB生成对应着XML顶层元素和顶层复杂类型元素Java类和接口。在一个XML模式中,一个元素由<xs:element/>表示,一个复杂类型元素由<xs:complexType/>表示。这篇教程列举了一个能够表示一篇在科学杂志上发表的文章的示例模式,同时这个示例模式将会被JAXB绑定编译器编译。XML模式,catalog.xsd,如下:

<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<xsd:element name="catalog" type="catalogType"/>
<xsd:complexType name="catalogType"> 
<xsd:sequence>  
<xsd:element ref="journal"  minOccurs="0" maxOccurs="unbounded"/> 
</xsd:sequence> 
<xsd:attribute name="section" type="xsd:string"/> 
<xsd:attribute name="publisher" type="xsd:string"/>
</xsd:complexType>
<xsd:element name="journal" type="journalType"/>
<xsd:complexType name="journalType"> 
<xsd:sequence>  
<xsd:element ref="article"  minOccurs="0" maxOccurs="unbounded"/> 
</xsd:sequence>
</xsd:complexType>
<xsd:element name="article" type="articleType"/>
<xsd:complexType name="articleType"> 
<xsd:sequence>  
<xsd:element name="title" type="xsd:string"/>  
<xsd:element name="author" type="xsd:string"/> 
</xsd:sequence> 
<xsd:attribute name="level" type="xsd:string"/> 
<xsd:attribute name="date" type="xsd:string"/>
</xsd:complexType></xsd:schema>

      一些XML模式的构造不被JAXB支持。如果这些不被支持的构造包含在了模式中,那么当你试图用xjc来生成Java类时将会报错。下列模式元素不被支持:xs:any, xs:anyAttribute, xs:notation, xs:redefine, xs:key, xs:keyref, xs:unique. 下列模式的属性不被支持: complexType.abstract, element.abstract, element.substitutionGroup, xsi:type, complexType.block, complexType.final, element.block, element.final, schema.blockDefault, schema.finalDefault.

生成Java

      xjc工具基于此模式来绑定一个模式到Java类。针对本文的示例模式来进行绑定的命令是:
>xjc catalog.xsd

      xjc命令行接口的一些选项列如下:

-nv        对于输入的模式不执行严格的XML验证
-b <file>       
指定外部的绑定文件
-d <dir>       
指定生成的文件的存放路径
-p <pkg>       
指定目标包
-classpath <arg>        
指定classpath
-use-runtime <pkg>        impl.runtime
包不被生成
-xmlschema       
输入的模式是一个W3C XML模式(默认)

       对于示例模式catalog.xsd来说,xjc将会生成45个类,显示在如下xjc的输出中:

parsing a schema...
compiling a schema...
generatedimplruntimeErrorHandlerAdaptor.java
generatedimplruntimeMSVValidator.java
generatedimplruntimeNamespaceContext2.java
generatedimplruntimeUnmarshallableObject.java
generatedimplruntimeMarshallerImpl.java
generatedimplruntimeValidationContext.java
generatedimplruntimeUnmarshallerImpl.java
generatedimplruntimeDefaultJAXBContextImpl.java
generatedimplruntimeContentHandlerAdaptor.java
generatedimplruntimeGrammarInfoFacade.java
generatedimplruntimeUnmarshallingContext.java
generatedimplruntimeUnmarshallingEventHandlerAdaptor.java
generatedimplruntimeXMLSerializable.java
generatedimplruntimeDiscarder.java
generatedimplruntimePrefixCallback.java
generatedimplruntimeSAXMarshaller.java
generatedimplruntimeNamespaceContextImpl.java
generatedimplruntimeUnmarshallingEventHandler.java
generatedimplruntimeGrammarInfo.java
generatedimplruntimeInterningUnmarshallerHandler.java
generatedimplruntimeValidatableObject.java
generatedimplruntimeGrammarInfoImpl.java
generatedimplruntimeValidatingUnmarshaller.java
generatedimplruntimeValidatorImpl.java
generatedimplruntimeSAXUnmarshallerHandlerImpl.java
generatedimplruntimeXMLSerializer.java
generatedimplruntimeUtil.java
generatedimplruntimeSAXUnmarshallerHandler.java
generatedimplruntimeAbstractUnmarshallingEventHandlerImpl.java
generatedimplArticleImpl.java
generatedimplArticleTypeImpl.java
generatedimplCatalogImpl.java
generatedimplCatalogTypeImpl.java
generatedimplJAXBVersion.java
generatedimplJournalImpl.java
generatedimplJournalTypeImpl.java
generatedArticle.java
generatedArticleType.java
generatedCatalog.java
generatedCatalogType.java
generatedJournal.java
generatedJournalType.java
generatedObjectFactory.java
generatedbgm.ser
generatedjaxb.properties

   对于示例XML模式中的每个顶层xs:element和顶层xs:complexType,都对应地生成了一个Java接口和一个Java类。同时也创建了一个工厂类(ObjectFactory.java,包含了创建接口对象的方法。可以在在篇文章的示例代码文件jaxb-java-resources.zip中找到ObjectFactory.java类。

      Catalog.java是对应顶层元素catalog生成的接口。从模式的元素中生成的接口扩展了javax.xml.bin.Elemnt类。

      Catalog.java

package generated;
public interface Catalog  
extends javax.xml.bind.Element, generated.CatalogType{}

      CatalogType.java是对应顶层复杂元素catalogType生成的接口。CatalogType接口对应catalog元素的每个属性指定了settergetter方法,还有对应catalog元素中的journal元素的一个getter方法。

      CatalogType.java

package generated;
public interface CatalogType
{   
java.lang.String getSection();   
void setSection(java.lang.String value);   
java.util.List getJournal();   
java.lang.String getPublisher();   
void setPublisher(java.lang.String value);
}
 
      CatalogImpl.java
CatalogTypeImpl.java是分别对应Catalog.java CatalogType.java接口的实现类。

      Java类中创建一个XML文档

      这一节中,一个示例XMl文档将会通进JAXBJava类被创建。示例XML文档,catalog.xml,如下显示:

<?xml version="1.0" encoding="UTF-8"?>
<catalog xmlns="http://www.w3.org/2001/XMLSchema-Instance"        section="Java Technology"        publisher="IBM  developerWorks">    
<journal>                
<article level="Intermediate"  date="January-2004" >         
<title>Service Oriented Architecture Frameworks </title>          
<author>Naveen Balani</author>      
</article>     
<article level="Advanced" date="October-2003"  >         
<title>Advance DAO Programming</title>          
<author>Sean Sullivan</author>      
</article>      
<article level="Advanced" date="May-2002"  >         
<title>Best Practices in EJB Exception Handling  </title>         
<author>Srikanth Shenoy    </author>      
</article>   
</journal>
</catalog>

      Java类中创建一个CatalogImpl, 并且使用一个Marshaller(排列者)将CatalogImpl序列化来生成一个XML文档。

      创建Marshaller(排列者)

      首先,导入javax.xml.bind包,其中包含了Marshaller, UnMarshaller, JAXBContext类。Marshaller类用来将一个Java类转换为XML数据。UnMarshaller类转换一个XML文档成Java对象。

import javax.xml.bind.*;

  创建一个JAXBContext

      一个JAXBContext对象被用来实现JAXB绑定框架的操作:marshal, unmarshalvalidate。应用使用静态方法newInstance(String contextPath)来创建一个新实例(对象)。contextPath指明一组由模式生成的接口的包名。

JAXBContext jaxbContext=JAXBContext.newInstance("generated");

      目录generated包含了JAXB生成的类和接口

      使用createMarshaller方法创建一个MarshallerMarshaller类重载了marshal方法,可以将Java对象序列化(也就是,转换一个Java对象到XML数据)成SAX2事件,文档对象模型(DOM),OutputStream, javax.xml.transform.Result或者java.io.Writer对象。

Marshaller marshaller=jaxbContext.createMarshaller();

      XML文档创建一个Java对象:CatalogImpl

      为了创建一个Java对象,首选生成一个ObjectFactoryObjectFactory将会创建一个实现类的实例。对于每一个模式生成的Java类,ObjectFactory中定义了一个静态方法来创建一个它的对象。

ObjectFactory factory=new ObjectFactory();

      使用ObjectFactory类中的createCatalog来创建一个catalog元素。CatalogImplCatalog接口的实现类。
CatalogImpl catalog=(CatalogImpl)(factory
.createCatalog());

      使用CatalogImpl类中的setSection方法来设置catalog元素的section属性。
catalog.setSection("Java Technology");

      setPublisher方法来设置catalog元素的publisher属性。
catalog.setPublisher("IBM developerWorks");

      XML文档创建一个Java对象:JournalImplArticleImpl

      ObjectFactory类中的createJournal方法来创建一个jounal元素。JournalImplJournal接口的实现类。
JournalImpl journal=(JournalImpl)(factory.createJournal());

      journal元素加入catalog元素。从CatalogImpl得到JournalImpljava.util.List,并把journal元素加入到List中。
java.util.List journalList=ca
talog.getJournal();journalList.add(journal);

      使用ObjectFactory类的createArticle方法来创建journal中的article元素。ArticleImplArticle接口的实现类。
ArticleImpl article=(ArticleImpl)(factory.createArticle());

      使用ArticleImpl类中的setLevel方法来设置article元素的level属性。
article.se
tLevel("Intermediate");

      setDate方法设置articledate属性
article.setDate("January-2004");

      setTitle方法创建article元素的title属性
article.setTitle("Service Oriented Architecture Frameworks");

      setAuthor方法创建article元素的author属性
article.setAuthor("Naveen
Balani");

      article元素加入journal元素中。从JournalImpl中得到ArticleImpljava.util.List,并将article元素加入List中。
java.util.List  articleList=journal.getArticle(); articleList.add(article);

      与创建article元素的过程相类似,其它article元素也将被创建用来生成示例XML文档catalog.xml

      Java对象序列化为一个XML文档

      Marshaller类中的marshal方法来将CatalogImpl对象序列化为一个XML文档。CatalogImpl对象被序列化为一个OutputStream
marshaller.marshal(catalog, new FileOutputStream(xmlDocument));

      xmlDocument是输出的XMLjava.io.File对象,它代表的是本节一开始所展示的XML文档。JAXBConstructor.java,这个程序用来从Java类中生成一个XML文档,也在这篇文章的示例代码文件中。

      总结

      JAXB提供了一个绑定编译器xjc, 从一个模式中生成Java对象,然后这些Java对象可以序列化为一个XML文档。但是,JAXB有一个限制:它不支持所有的XML模式结构。

JAXBJava Architecture for XML Binding) 是一个业界的标准,是一项可以根据XML Schema产生Java类的技术。该过程中,JAXB也提供了将XML实例文档反向生成Java对象树的方法,并能将Java对象树的内容重新写到XML实例文档。从另一方面来讲,JAXB提供了快速而简便的方法将XML模式绑定到Java表示,从而使得Java开发者在Java应用程序中能方便地结合XML数据和处理函数。

编辑本段使用

  “xjc”工具可以用来将XML模式或其他类型模式文件(Java 1.6试验性地支持RELAX NGDTD以及WSDL)转换为Java类。Java类使用javax.xml.bind.annotation包下的Java 标注,例如@XmlRootElement@XmlElementXML列表序列表示为java.util.List类型的属性,通过JAXBContext可以创建Marshallers(将Java对象转换成XML)和Unmarshallers(将XML解析为Java对象)。

  此外,JAXB包括了一个“schemagen”工具,能够执行“xjc”的反向操作,通过一组标注的Java类创建一个XML模式。

编辑本段缺省的数据类型绑定

  下面的表格列出了JAXBXML数据类型和Java数据类型的映射。

  

XML Schema类型

Java数据类型

xsd:string

java.lang.String

xsd:positiveInteger

java.math.BigInteger

xsd:int

int

xsd:long

long

xsd:short

short

xsd:decimal

java.math.BigDecimal

xsd:float

float

xsd:double

double

xsd:boolean

boolean

xsd:byte

byte

xsd:QName

javax.xml.namespace.QName

xsd:dateTime

javax.xml.datatype.XMLGregorianCalendar

xsd:base64Binary

byte[]

xsd:hexBinary

byte[]

xsd:unsignedInt

long

xsd:unsignedShort

int

xsd:unsignedByte

short

xsd:time

javax.xml.datatype.XMLGregorianCalendar

xsd:date

javax.xml.datatype.XMLGregorianCalendar

xsd:g

javax.xml.datatype.XMLGregorianCalendar

xsd:anySimpleType

java.lang.Object

xsd:anySimpleType

java.lang.String

xsd:duration

javax.xml.datatype.Duration

xsd:NOTATION

javax.xml.namespace.QName

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值