XSD-7 XJC 代碼生成器
7 XJC 代碼生成器
JAXB 支持兩種方式的XML與Java Bean 相互轉化,之前介紹過基於註解的方式,這節介紹另一種方式 xjc。xjc屬於jdk 的命令行工具,用於將schema文件生成java實體類。 在上一節中,我們已經得到了 schema 文件,現在的主要任務是將 schema 轉換爲 Java bean。
7.1 XJC 工具簡介
引用 stack overflow 上的描述:
JAXB (JSR-222) implementations convert instances of Java classes (that may contain annotations) to/from XML. XJC (XML to Java Compiler) is a utility for generating those objects from an XML schema. It is included as part of the JDK since Java SE 6.
xjc 是 JAXB 集成的工具之一,通過 xjc -version
查看 xjc 的版本
$>xjc -version
xjc 2.2.8-b130911.1802
使用 XJC 的轉換命令:
xjc book.xsd
7.2 XJC 的參數
演示的是最簡單的命令,使用了很多默認參數,實際上xjc支持的參數非常多,列舉常用的幾個參數及其含義。
- 參數
-b
含義:默認 file/dir,指定其他的binding 文件 或文件夾 - 參數
-d
含義:dir,默認爲generated,生成的文件存放在該文件夾下 - 參數
-p
含義:pkg,默認爲generated,生成的Java文件使用的包名 - 參數
-xmlschema
含義:默認,指定輸入爲W3C XML Schema - 參數
-relaxng
含義:指定輸入爲 RELAX NG - 參數
-relaxng-compact
含義:指定輸入爲 RELAX NG compact - 參數
dtd
含義:指定輸入爲 XML DTD - 參數
-version
含義:查看 xjc 的版本
-
指定生成的 java 文件的包名:
xjc -p com.traing.bean book.xsd
可以在生成的文件E:/JAXB/com/traing/book/Book.java
中發現指定的包名和目錄樹。package com.traing.bean
; -
指定生成的 java 文件路徑:
xjc book.xsd -d e:\JAXB\com
可以發現生成的文件位於E:/JAXB/com/Book.java
,值得注意的是,這裏的e:\JAXB\com
必須是一個存在的文件夾,否則不成功,錯誤提示拒絕寫入不存在的目錄 “e:\JAXB\com
”。 -
將其他格式的 schema 轉化爲Java對象:
xjc student.dtd -dtd
可以發現生成的文件E:/JAXB/generated/Student.java
,此外還有其他的一些文件。 -
一次性指定多個需要轉換 schema 文件:
xjc student.xsd grade.xsd
不用一個個轉換了,可以指定多個schema文件,不過兩個 schema 文件不能有重複的屬性。
7.3 XJC 轉換複雜類型的 Schema
新建 book.xsd 文檔,保存以下 schema 內容。
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified">
<xs:element name="book" type="Book"/>
<xs:complexType name="Book">
<xs:sequence>
<xs:element name="id" type="xs:string"/>
<xs:element name="name" type="xs:string"/>
<xs:element name="price" type="xs:decimal"/>
</xs:sequence>
</xs:complexType>
</xs:schema>
通過 IntelliJ IDEA 的右鍵菜單 generate XML Document from XSD Schema
功能,以上 schema 用於解析以下 xml 文檔。
<book>
<id>string</id>
<name>string</name>
<price>1000.00</price>
</book>
執行 xjc 轉換指令
xjc book.xsd
生成 Book.java 和 ObjectFactory.java 文件
Book.java 文件
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "Book", propOrder = {
"id",
"name",
"price"
})
public class Book {
@XmlElement(required = true)
protected String id;
@XmlElement(required = true)
protected String name;
@XmlElement(required = true)
protected BigDecimal price;
// getters, setters
}
ObjectFactory.java 文件
@XmlRegistry
public class ObjectFactory {
private final static QName _Book_QNAME = new QName("", "book");
public Book createBook() {
return new Book();
}
@XmlElementDecl(namespace = "", name = "book")
public JAXBElement<Book> createBook(Book value) {
return new JAXBElement<Book>(_Book_QNAME, Book.class, null, value);
}
}
獨立的 Book 模板類型(schema type),使 xjc 在 ObjectFactory.java 中生成對應的JAXBElement<Book> createBook(Book value)
函數;使 Book.java 的類註解取消了@XmlRootElement(name = "book")
,填充name到 @XmlType
註解;使應用程序開發者,可以使用已有對象實例進行XML序列化與反序列化。
xjc 對 xsd 文檔進行代碼生成時,遵循如下規律:
- 對獨立模板類型和內嵌類型的節點,提供無參實例生成函數,如
Book createBook()
- 對使用獨立模板類型的元素(
<xs:element>
),提供有參實例轉換函數,如JAXBElement<Book> createBook(Book value)
7.4 XJC 轉換含有集合類型的 Schema (1)
新建 book.xsd 文檔,保存以下 schema 內容。
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified">
<xs:element name="books" type="Books"/>
<xs:complexType name="Books">
<xs:sequence>
<xs:element maxOccurs="unbounded" name="book" type="Book"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="Book">
<xs:sequence>
<xs:element name="name" type="xs:string"/>
<xs:element name="price" type="xs:decimal"/>
</xs:sequence>
<xs:attribute name="id" use="required" type="xs:string"/>
</xs:complexType>
</xs:schema>
以上 schema 用於解析以下 xml 文檔。
<books>
<!--1 or more repetitions:-->
<book id="string">
<name>string</name>
<price>1000.00</price>
</book>
</books>
執行 xjc 轉換指令
xjc book.xsd
生成 Book.java, Books.java 和 ObjectFactory.java 文件
Book.java 文件
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "Book", propOrder = {
"name",
"price"
})
public class Book {
@XmlElement(required = true)
protected String name;
@XmlElement(required = true)
protected BigDecimal price;
@XmlAttribute(name = "id", required = true)
protected String id;
// getters, setters
}
Books.java 文件
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "Books", propOrder = {
"book"
})
public class Books {
@XmlElement(required = true)
protected List<Book> book;
public List<Book> getBook() {
if (book == null) {
book = new ArrayList<Book>();
}
return this.book;
}
}
ObjectFactory.java 文件
@XmlRegistry
public class ObjectFactory {
private final static QName _Books_QNAME = new QName("", "books");
public Books createBooks() {
return new Books();
}
public Book createBook() {
return new Book();
}
@XmlElementDecl(namespace = "", name = "books")
public JAXBElement<Books> createBooks(Books value) {
return new JAXBElement<Books>(_Books_QNAME, Books.class, null, value);
}
}
7.5 XJC 轉換含有集合類型的 Schema (2)
新建 book.xsd 文檔,保存以下 schema 內容。
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified">
<xs:element name="shop" type="Shop"/>
<xs:complexType name="Shop">
<xs:sequence>
<xs:element name="name" type="xs:string"/>
<xs:element name="books" type="Books"/>
</xs:sequence>
<xs:attribute name="id" use="required" type="xs:string"/>
</xs:complexType>
<xs:complexType name="Books">
<xs:sequence>
<xs:element maxOccurs="unbounded" name="book" type="Book"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="Book">
<xs:sequence>
<xs:element name="name" type="xs:string"/>
<xs:element name="price" type="xs:decimal"/>
</xs:sequence>
<xs:attribute name="id" use="required" type="xs:string"/>
</xs:complexType>
</xs:schema>
以上 schema 用於解析以下 xml 文檔。
<shop id="string">
<name>string</name>
<books>
<!--1 or more repetitions:-->
<book id="string">
<name>string</name>
<price>1000.00</price>
</book>
</books>
</shop>
執行 xjc 轉換指令
xjc book.xsd
生成 Book.java, Books.java,Shop.java 和 ObjectFactory.java 文件
Book.java 文件
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "Book", propOrder = {
"name",
"price"
})
public class Book {
@XmlElement(required = true)
protected String name;
@XmlElement(required = true)
protected BigDecimal price;
@XmlAttribute(name = "id", required = true)
protected String id;
// getters, setters
}
Books.java 文件
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "Books", propOrder = {
"book"
})
public class Books {
@XmlElement(required = true)
protected List<Book> book;
public List<Book> getBook() {
if (book == null) {
book = new ArrayList<Book>();
}
return this.book;
}
}
Shop.java 文件
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "Shop", propOrder = {
"name",
"books"
})
public class Shop {
@XmlElement(required = true)
protected String name;
@XmlElement(required = true)
protected Books books;
@XmlAttribute(name = "id", required = true)
protected String id;
// getters, setters
}
ObjectFactory.java 文件
@XmlRegistry
public class ObjectFactory {
private final static QName _Shop_QNAME = new QName("", "shop");
public Shop createShop() {
return new Shop();
}
public Books createBooks() {
return new Books();
}
public Book createBook() {
return new Book();
}
@XmlElementDecl(namespace = "", name = "shop")
public JAXBElement<Shop> createShop(Shop value) {
return new JAXBElement<Shop>(_Shop_QNAME, Shop.class, null, value);
}
}
7.6 類型綁定 bindings.xml
XML 與 Java 都有自身語言的數據類型,它們大多數是對應的,有時候我們想更改這種映射關係,就需要使用到 bindings.xml。
如下是一個簡單的映射關係,表示將 XML 中的 xs:date 類型映射到 Java 中的 java.util.Calendar。
<bindings xmlns="http://java.sun.com/xml/ns/jaxb" version="2.0"
xmlns:xs="http://www.w3.org/2001/XMLSchema">
<globalBindings>
<javaType name="java.util.Calendar" xmlType="xs:date"
parseMethod="javax.xml.bind.DatatypeConverter.parseDate"
printMethod="javax.xml.bind.DatatypeConverter.printDate" />
</globalBindings>
</bindings>
這裏使用到了內置的解析函數parseDate。
單個映射文件 xjc book.xsd -b bindings.xml
多個映射文件,需要每一個都指定-b參數 xjc book.xsd -b binding1.xml -b binding2.xml
如果不能滿足業務需求,還可以自己實現解析規則:
public class DateAdapter {
public static Date parseDate(String s) {
return DatatypeConverter.parseDate(s).getTime();
}
public static String printDate(Date dt) {
Calendar cal = new GregorianCalendar();
cal.setTime(dt);
return DatatypeConverter.printDate(cal);
}
}
代碼置於 com.csdn.jaxb.DateAadpter,編寫自定義mybindings.xml
<bindings xmlns="http://java.sun.com/xml/ns/jaxb"
version="2.0"
xmlns:xs="http://www.w3.org/2001/XMLSchema">
<globalBindings>
<javaType name="java.util.Date" xmlType="xs:date"
parseMethod="com.csdn.jaxb.DateAadpter.parseDate"
printMethod="com.csdn.jaxb.DateAdapter.printDate"
/>
</globalBindings>
</binding>
指定爲自己定義的映射文件(如果要直接在終端運行,需要配置Java 的 CLASSPATH) xjc book.xsd -b mybindings.xml
上一章:XSD-6 Schema 面向對象之複合元素 complexType
目錄:學習 JAXB
下一章:XSD-8 JAXB 驗證 XSD Schema 限定