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 的版本
  1. 指定生成的 java 文件的包名: xjc -p com.traing.bean book.xsd
    可以在生成的文件 E:/JAXB/com/traing/book/Book.java 中發現指定的包名和目錄樹。 package com.traing.bean;

  2. 指定生成的 java 文件路徑: xjc book.xsd -d e:\JAXB\com
    可以發現生成的文件位於 E:/JAXB/com/Book.java,值得注意的是,這裏的 e:\JAXB\com 必須是一個存在的文件夾,否則不成功,錯誤提示拒絕寫入不存在的目錄 “e:\JAXB\com”。

  3. 將其他格式的 schema 轉化爲Java對象: xjc student.dtd -dtd
    可以發現生成的文件 E:/JAXB/generated/Student.java,此外還有其他的一些文件。

  4. 一次性指定多個需要轉換 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 限定


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章