原帖地址:http://manyuewushuang.iteye.com/blog/684285
http://manyuewushuang.iteye.com/blog/684379
http://manyuewushuang.iteye.com/blog/684391
http://manyuewushuang.iteye.com/blog/685910
http://java.sun.com/javaee/5/docs/tutorial/doc/bnazf.html
https://jaxb.dev.java.net/guide/ (详细学习)
Jaxb中两个重要的过程:
1. 编组 Marshal(java 2 xml) 则是指将一个内存对象以XML文档形式进行编组处理的过程。
编组是把一些 Java 对象转化成一个(或多个) XML 文档。
2. 解组 Unmarshaller(xml 2 java)与编组相反是一个将XML文档解析为内存对象的过程。
JAXB数据绑定步骤:
l Generate classes: 使用JAXB Binding Compiler(xjc命令)根据XML Schema生成Java代码。
l Compile classes: 编译所有生成的Java源代码。
l Unmarshal: 将XML文档内容解组到内存中。
l Generate content tree: 解组过程产生由JAXB生成的一系列classes的数据对象的实例的content tree。这个content tree代表了这个XML文档的结构以及内容。
l Validate (optional): 解组过程中带有的可选的校验过程,包括在生成content tree之前校验xml文档。
l Process content: 应用程序可以通过JAXB生成的一系列content tree修改xml文档内容。
l Marshal: 处理过的content tree 的内容编组到xml文档中,在这之前可能进行过校验。
JAXB将XML Schema表示为Java对象:
l 根据Schema中定义的xml elements生成的一系列类文件;
l 一个ObjectFactory类,用于产生绑定的Java类的实例的工厂。
<!--EndFragment-->
一个Schema中的类型定义:
l 基本类型
l 集合类型
l Predicate(??谓语??)
Schema-to-Java Mapping(here list the mapping of XML data types to java data types in JAXB):
<!--EndFragment-->
JAXBElement Object:
当xml element不能用Java表示时,此时提供一个JAXBElement,用于getting/setting object name 和object value .
Java-to-Schema Mapping(here list the mapping of Java classes to XML data types):
在Java EE5 中的JAXB注解元素在 javax.xml.bind.annotation包中。
-
standalone = "yes" ?>
- <project basedir="." default="compile">
- <!-- 设置jwsdp主目录 -->
- <property name="jwsdp.home" value="D:/Java/Sun/jwsdp-2.0" />
- <property name="classes.home" value="target/classes" />
- <property name="generate.code.home" value="src/primer" />
- <path id="classpath">
- <pathelement path="src" />
- <pathelement path="${classes.home}" />
- <!--for use with bundled ant-->
- <fileset dir="${jwsdp.home}" includes="jaxb/lib/*.jar" />
- <fileset dir="${jwsdp.home}" includes="sjsxp/lib/*.jar" />
- <fileset dir="${jwsdp.home}" includes="jwsdp-shared/lib/activation.jar" />
- <fileset dir="${jwsdp.home}" includes="jwsdp-shared/lib/resolver.jar" />
- </path>
- <!-- 定义xjc任务 -->
- <taskdef name="xjc" classname="com.sun.tools.xjc.XJCTask">
- <classpath refid="classpath" />
- </taskdef>
- <target name="generate-code" >
- <echo message="Compiling the schema..." />
- <!-- 使用xjc任务根据xsd文件生成Java代码 -->
- <xjc schema="po.xsd" package="primer.po" destdir="src">
- <produces dir="src/primer.po" includes="**/*.java" />
- </xjc>
- </target>
- <!--compile Java source files-->
- <target name="compile" depends="generate-code" description="Compile all Java source files">
- <echo message="Compiling the java source files..." />
- <mkdir dir="${classes.home}"/>
- <javac destdir="${classes.home}" debug="on">
- <src path="src" />
- <classpath refid="classpath" />
- </javac>
- </target>
- <target name="clean" description="删除生成的class文件及由xsd生成的Java代码">
- <delete dir="${classes.home}" />
- <delete deleteonexit="true" dir="${generate.code.home}" />
- </target>
- </project>
运行ant文件后(运行默认任务即可),运行Main类,可在控制台打印修改原xml文档后的内容,并可在project目录下生成一个newpo.xml文件:
- package modifymarshal;
- import java.io.File;
- import java.io.FileInputStream;
- import java.io.FileOutputStream;
- import java.io.IOException;
- import java.math.BigDecimal;
- import java.math.BigInteger;
- import java.util.Date;
- import java.util.GregorianCalendar;
- import java.util.List;
- import java.util.Locale;
- import java.util.TimeZone;
- import javax.xml.bind.JAXBContext;
- import javax.xml.bind.JAXBElement;
- import javax.xml.bind.JAXBException;
- import javax.xml.bind.Marshaller;
- import javax.xml.bind.Unmarshaller;
- import javax.xml.datatype.Duration;
- import javax.xml.datatype.XMLGregorianCalendar;
- import javax.xml.namespace.QName;
- import com.sun.org.apache.bcel.internal.generic.GETSTATIC;
- import com.sun.org.apache.xerces.internal.jaxp.datatype.XMLGregorianCalendarImpl;
- // import java content classes generated by binding compiler
- import primer.po.*;
- import primer.po.Items.Item;
- /**
- *
- * @author liu_yming
- *
- */
- public class Main {
- // This sample application demonstrates how to modify a java content
- // tree and marshal it back to a xml data
- public static void main(String[] args) {
- try {
- // 创建一个 JAXBContext 的实例处理生成的primer.po包底下的类
- JAXBContext jc = JAXBContext.newInstance("primer.po");
- // create an Unmarshaller
- Unmarshaller u = jc.createUnmarshaller();
- // 已经废弃的setValidating方法
- // u.setValidating(true);
- // 读取xml文档并unmarshal(xml2java 解组)至content tree
- JAXBElement poe = (JAXBElement) u.unmarshal(
- new FileInputStream("po.xml"));
- PurchaseOrderType po = (PurchaseOrderType) poe.getValue();
- // 输出po.xml文档中的内容
- USAddress shipTo = po.getShipTo();
- System.out.println("shipTo name: " + shipTo.getName());
- System.out.println("shipto country: " + shipTo.getCountry());
- System.out.println("**********************************");
- USAddress billTo = po.getBillTo();
- System.out.println("billTo name: " + billTo.getName());
- System.out.println("billTo country: " + billTo.getCountry());
- System.out.println("**********************************");
- Items items = po.getItems();
- List<Item> itemList = items.getItem();
- for (Item item:itemList) {
- System.out.println("item attribute partNum : " + item.getPartNum());
- System.out.println("item element comment : " + item.getComment());
- System.out.println("item element ProductName : " + item.getProductName());
- System.out.println("item element Quantity : " + item.getQuantity());
- System.out.println("item element ShipDate : " + item.getShipDate());
- System.out.println("-----------------------------");
- }
- System.out.println("**********************************");
- // change the billto address
- USAddress newBillTo = po.getBillTo();
- newBillTo.setCountry("CN");
- newBillTo.setName("Kevin Liu");
- newBillTo.setStreet("XueYuan road 388");
- newBillTo.setCity("KunShan");
- newBillTo.setState("JiangSu");
- newBillTo.setZip(new BigDecimal("258311"));
- // change the first item
- Item newItem = itemList.get(0);
- newItem.setPartNum("444-CN");
- newItem.setComment("水泥杀手");
- newItem.setProductName("安踏");
- newItem.setShipDate(XMLGregorianCalendarImpl.parse("20100603"));
- newItem.setQuantity(BigInteger.valueOf(3));
- // 创建一个Marshaller 并marshal(编组 java2xml)只newpo.xml文件并在控制台打印输出
- Marshaller m = jc.createMarshaller();
- m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
- // 输出的控制台
- m.marshal(poe, System.out);
- // 输出到新的文件
- //m.marshal(poe, new FileOutputStream(new File("newpo.xml")));
- } catch (JAXBException je) {
- je.printStackTrace();
- } catch (IOException ioe) {
- ioe.printStackTrace();
- }
- }
- }
定制JAXB绑定:
l 在XML Schema中使用JAXB注解,使用<xsd:appinfo>内嵌于<xsd:annotation>中,在<xsd:appinfo>中使用<jxb:xx>标签定义各元素与class的对应关系。
l 直接使用XML Schema 配合自定义JAXB的.xjb文件
inline绑定:
- <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
- xmlns:jxb="http://java.sun.com/xml/ns/jaxb"
- jxb:version="1.0">
- <xsd:annotation>
- <xsd:documentation>
- 文件描述
- </xsd:documentation>
- <xsd:appinfo>
- <jxb:globalBindings
- fixedAttributeAsConstantProperty="false"
- collectionType="java.util.Vector"
- typesafeEnumBase="xsd:NCName"
- choiceContentProperty="false"
- typesafeEnumMemberName="generateError"
- enableFailFastCheck="false"
- generateIsSetMethod="false"
- underscoreBinding="asCharInWord"/>
- <jxb:schemaBindings>
- <jxb:package name="primer.myPo"><!-- 生成Java代码时候的包路径 -->
- <jxb:javadoc>
- <![CDATA[<body> Package level documentation for generated package primer.myPo.</body>]]>
- </jxb:javadoc>
- </jxb:package>
- <jxb:nameXmlTransform>
- <jxb:elementName suffix="Element"/>
- </jxb:nameXmlTransform>
- </jxb:schemaBindings>
- </xsd:appinfo>
- </xsd:annotation>
- <xsd:element name="purchaseOrder" type="PurchaseOrderType"/>
- <xsd:element name="comment" type="xsd:string"/><!-- 映射为普通的String类型元素 -->
- <xsd:complexType name="PurchaseOrderType">
- <xsd:annotation>
- <xsd:appinfo>
- <jxb:class name="POType">
- <jxb:javadoc>
- </jxb:javadoc>
- </jxb:class>
- </xsd:appinfo>
- </xsd:annotation>
- <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>
- <!-- 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:simpleType name="ZipCodeType">
- <xsd:annotation>
- <xsd:appinfo><!-- 使用自定义类型转换器 -->
- <jxb:javaType name="int"
- parseMethod="inlinecustomize.primer.MyDatatypeConverter.parseIntegerToInt"
- printMethod="inlinecustomize.primer.MyDatatypeConverter.printIntToInteger" />
- </xsd:appinfo>
- </xsd:annotation>
- <xsd:restriction base="xsd:integer">
- <xsd:minInclusive value="10000"/>
- <xsd:maxInclusive value="99999"/>
- </xsd:restriction>
- </xsd:simpleType>
- </xsd:schema>
external 绑定需要一个标准的xsd文件以及一个外部的xjb格式文件:
- <jxb:bindings version="1.0"
- xmlns:jxb="http://java.sun.com/xml/ns/jaxb"
- xmlns:xs="http://www.w3.org/2001/XMLSchema">
- <jxb:bindings schemaLocation="po.xsd" node="/xs:schema">
- <jxb:globalBindings
- fixedAttributeAsConstantProperty="false"
- collectionType="java.util.Vector"
- typesafeEnumBase="xs:NCName"
- choiceContentProperty="false"
- typesafeEnumMemberName="generateError"
- enableFailFastCheck="false"
- generateIsSetMethod="false"
- underscoreBinding="asCharInWord"/>
- <jxb:schemaBindings>
- <jxb:package name="primer.myPo">
- <jxb:javadoc><![CDATA[<body>Package level documentation for generated package primer.myPo.</body>]]>
- </jxb:javadoc>
- </jxb:package>
- <jxb:nameXmlTransform>
- <jxb:elementName suffix="Element"/>
- </jxb:nameXmlTransform>
- </jxb:schemaBindings>
- <jxb:bindings node="//xs:complexType[@name='PurchaseOrderType']">
- <jxb:class name="POType">
- <jxb:javadoc>A <b>Purchase Order</b> consists of addresses and items.</jxb:javadoc>
- </jxb:class>
- </jxb:bindings>
- <jxb:bindings node="//xs:complexType[@name='USAddress']">
- <jxb:class>
- <jxb:javadoc><![CDATA[First line of documentation for a <b>USAddress</b>.]]></jxb:javadoc>
- </jxb:class>
- <jxb:bindings node=".//xs:element[@name='name']">
- <jxb:property name="toName"/>
- </jxb:bindings>
- <jxb:bindings node=".//xs:element[@name='zip']">
- <jxb:property name="zipCode"/>
- </jxb:bindings>
- </jxb:bindings> <!-- node="//xs:complexType[@name='USAddress']" -->
- <jxb:bindings node="//xs:complexType[@name='Items']">
- <jxb:bindings node=".//xs:element[@name='item']//xs:element[@name='quantity']">
- <jxb:property generateIsSetMethod="true"/>
- <jxb:bindings node=".//xs:attribute[@name='partNum']">
- <jxb:property name="partNumber"/>
- </jxb:bindings>
- </jxb:bindings>
- <jxb:bindings node="//xs:simpleType[@name='ZipCodeType']">
- <jxb:javaType name="int"
- parseMethod="javax.xml.bind.DatatypeConverter.parseInt"
- printMethod="javax.xml.bind.DatatypeConverter.printInt"/>
- </jxb:bindings>
- </jxb:bindings> <!-- schemaLocation="po.xsd" node="/xs:schema" -->
- </jxb:bindings>
Java-to-Schema:
@XmlAccessorOrder @XmlType.propOrder 用于指明xml schema元素的顺序
使用@XmlAccessorOrder:
包括XmlAccessorOrder.UNDEFINED XmlAccessorOrder.ALPHABETICAL两个值,默认为UNDEFINED(无序),XmlAccessorOrder.ALPHABETICAL是指按属性的字母顺序排序。
当@XmlAccessorOrder定义在一个package之上时候(Package annotations must be in file package-info.java),此包下的所有类都遵守@XmlAccessorOrder定义的规则;当它定义在类之上时,只有该类的内容遵守规则。
就近原则:如果出现在package之上使用@XmlAccessorOrder并且在该包下的某个类又使用了@XmlAccessorOrder,那在该类上定义的@XmlAccessorOrder规则才起作用,如在package上声明@XmlAccessorOrder(XmlAccessOrder.ALPHABETICAL),而在某类上声明为UNDEFINED,则该类遵守的规则为UNDEFINED。
使用@XmlType.propOrder:
propOrder可以定义class中字段出现在xml中的顺序,class中所有public的字段必须列的propOrder的参数列表中,如果不想将某public字段列在列表中,可在字段上使用@XmlTransient or @XmlAttribute注解标识。
默认的内容顺序为@XmlType.propOrder is {} or {""}(not active 可认为无序?),在这种情况下,@XmlAccessorOrder 注解具有优先权。当@XmlAccessorOrder 与@XmlType.propOrder同时出现时,propOrder总是具有优先权(最终起作用)。
XmlAdapter 接口和 @XmlJavaTypeAdapter 注解:
使用这两个主要是为了那种 xml data type无法映射为Java object而准备的,比如Collection和Map及实现类等。
例:@XmlJavaTypeAdapter(AdapterPurchaseListToHashMap.class)// 使用自定义的实现 XmlAdapter 接口的适配器 for custom marshaling.
@XmlAttribute:
@XmlType:
@XmlRootElement:
@XmlSchemaType:使用该注解将字段映射到xml内置类型,如xs:date、xs:duration
@XmlType:使用该注解将一个class或一个enum映射成为一个 XML Schema type
JAXB Architectrual Overview:
A JAXB implementation consists of the following architectural components:
l Schema compiler: 将XML schema文件映射为相对应的Java元素。
l Schema generator: 与 Schema compiler反向的过程,将Java元素映射为schema。
l Binding runtime framework: 绑定运行时框架,即JAXB的编组及解组过程。
The JAXB Binding Proecss