В предыдущих статьях я сравнивал JAXB ( JSR-222 ) с Simple и XStream при запуске из объектов Java. В этой статье я буду сравнивать JAXB с XMLBeans при запуске из схемы XML. Я буду использовать XMLBeans 2.5.0 (декабрь 2009), которая является последней версией.
Ниже приведена схема XML, которая будет использоваться для генерации моделей нашего домена.
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns="http://www.example.com"
targetNamespace="http://www.example.com"
elementFormDefault="qualified">
<xs:element name="customer">
<xs:complexType>
<xs:sequence>
<xs:element name="name" type="xs:string"/>
<xs:element name="address" type="address"/>
<xs:element
name="phone-number"
type="phone-number"
minOccurs="0"
maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:complexType name="address">
<xs:sequence>
<xs:element name="street" type="xs:string"/>
<xs:element name="city" type="xs:string"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="phone-number">
<xs:simpleContent>
<xs:extension base="xs:string">
<xs:attribute name="type" type="xs:string"/>
</xs:extension>
</xs:simpleContent>
</xs:complexType>
</xs:schema>
Ниже приведен вызов для генерации классов XMLBeans из нашей XML-схемы. В этом примере мы будем использовать
флаг -srconly для генерации только источника.
|
1 |
scomp -d out -srconly customer.xsd |
Ниже приведены все артефакты, сгенерированные XMLBeans. Двоичные файлы XML-схемы (XSB) содержат метаданные, необходимые для выполнения привязки и проверки:
- ком / пример
- Address.java
- CustomerDocument.java
- PhoneNumber.java
- ком / пример / осущ
- AddressImpl.java
- CustomerDocumentImpl.java
- PhoneNumberImpl.java
- schemaorg_apache_xmlbeans
- Элемент / http_3A_2F_2Fwww_2Eexample_2Ecom
- customer.xsb
- javaname / ком / пример
- Address.xsb
- CustomerDocument.xsb
- PhoneNumber.xsb
-
- CustomerDocument
- Customer.xsb
- CustomerDocument
- Пространство имен / http_3A_2F_2Fwww_2Eexample_2Ecom
- xmlns.xsb
- ЦСИ
- customer.xsd
- Система / s16C99350D7D3A2544A7BFD5E35CA8BC8
- address6f49type.xsb
- customer3fdddoctype.xsb
- customer11d7elemtype.xsb
- customerelement.xsb
- index.xsb
- phonenumber9c83type.xsb
- TypeSystemHolder.class
- Тип / http_3A_2F_2Fwww_2Eexample_2Ecom
- address.xsb
- phone_2Dnumber.xsb
- Элемент / http_3A_2F_2Fwww_2Eexample_2Ecom
Ниже приведен вызов для генерации классов JAXB из схемы XML:
|
1 |
xjc -d out customer.xsd |
Ниже приведены все артефакты, сгенерированные JAXB. Обратите внимание, как много меньше артефактов создано:
- com.example
- Address.java
- Customer.java
- ObjectFactory.java
- package-info.java
- PhoneNumber.java
Модель Java — XMLBeans
XMLBeans создает набор интерфейсов Java, которые поддерживаются классами реализации. Ниже мы рассмотрим одну из этих пар.
Это один из интерфейсов, который генерируется XMLBeans. Стоит отметить несколько интересных вещей:
- Этот интерфейс предоставляет свойства POJO (строка 24) и DOM-подобную модель (строка 29).
- Этот интерфейс включает фабрику (строка 66). Эта фабрика используется для создания экземпляров объекта Address (строка 68) и для демаршалинга экземпляров Address из XML (строка 75).
package com.example;
/**
* An XML address(@http://www.example.com).
*
* This is a complex type.
*/
public interface Address extends org.apache.xmlbeans.XmlObject
{
public static final org.apache.xmlbeans.SchemaType type = (org.apache.xmlbeans.SchemaType)
org.apache.xmlbeans.XmlBeans.typeSystemForClassLoader(Address.class.getClassLoader(), "schemaorg_apache_xmlbeans.system.s16C99350D7D3A2544A7BFD5E35CA8BC8").resolveHandle("address6f49type");
/**
* Gets the "street" element
*/
java.lang.String getStreet();
/**
* Gets (as xml) the "street" element
*/
org.apache.xmlbeans.XmlString xgetStreet();
/**
* Sets the "street" element
*/
void setStreet(java.lang.String street);
/**
* Sets (as xml) the "street" element
*/
void xsetStreet(org.apache.xmlbeans.XmlString street);
/**
* Gets the "city" element
*/
java.lang.String getCity();
/**
* Gets (as xml) the "city" element
*/
org.apache.xmlbeans.XmlString xgetCity();
/**
* Sets the "city" element
*/
void setCity(java.lang.String city);
/**
* Sets (as xml) the "city" element
*/
void xsetCity(org.apache.xmlbeans.XmlString city);
/**
* A factory class with static methods for creating instances
* of this type.
*/
public static final class Factory
{
public static com.example.Address newInstance() {
return (com.example.Address) org.apache.xmlbeans.XmlBeans.getContextTypeLoader().newInstance( type, null ); }
public static com.example.Address newInstance(org.apache.xmlbeans.XmlOptions options) {
return (com.example.Address) org.apache.xmlbeans.XmlBeans.getContextTypeLoader().newInstance( type, options ); }
/** @param xmlAsString the string value to parse */
public static com.example.Address parse(java.lang.String xmlAsString) throws org.apache.xmlbeans.XmlException {
return (com.example.Address) org.apache.xmlbeans.XmlBeans.getContextTypeLoader().parse( xmlAsString, type, null ); }
public static com.example.Address parse(java.lang.String xmlAsString, org.apache.xmlbeans.XmlOptions options) throws org.apache.xmlbeans.XmlException {
return (com.example.Address) org.apache.xmlbeans.XmlBeans.getContextTypeLoader().parse( xmlAsString, type, options ); }
/** @param file the file from which to load an xml document */
public static com.example.Address parse(java.io.File file) throws org.apache.xmlbeans.XmlException, java.io.IOException {
return (com.example.Address) org.apache.xmlbeans.XmlBeans.getContextTypeLoader().parse( file, type, null ); }
public static com.example.Address parse(java.io.File file, org.apache.xmlbeans.XmlOptions options) throws org.apache.xmlbeans.XmlException, java.io.IOException {
return (com.example.Address) org.apache.xmlbeans.XmlBeans.getContextTypeLoader().parse( file, type, options ); }
public static com.example.Address parse(java.net.URL u) throws org.apache.xmlbeans.XmlException, java.io.IOException {
return (com.example.Address) org.apache.xmlbeans.XmlBeans.getContextTypeLoader().parse( u, type, null ); }
public static com.example.Address parse(java.net.URL u, org.apache.xmlbeans.XmlOptions options) throws org.apache.xmlbeans.XmlException, java.io.IOException {
return (com.example.Address) org.apache.xmlbeans.XmlBeans.getContextTypeLoader().parse( u, type, options ); }
public static com.example.Address parse(java.io.InputStream is) throws org.apache.xmlbeans.XmlException, java.io.IOException {
return (com.example.Address) org.apache.xmlbeans.XmlBeans.getContextTypeLoader().parse( is, type, null ); }
public static com.example.Address parse(java.io.InputStream is, org.apache.xmlbeans.XmlOptions options) throws org.apache.xmlbeans.XmlException, java.io.IOException {
return (com.example.Address) org.apache.xmlbeans.XmlBeans.getContextTypeLoader().parse( is, type, options ); }
public static com.example.Address parse(java.io.Reader r) throws org.apache.xmlbeans.XmlException, java.io.IOException {
return (com.example.Address) org.apache.xmlbeans.XmlBeans.getContextTypeLoader().parse( r, type, null ); }
public static com.example.Address parse(java.io.Reader r, org.apache.xmlbeans.XmlOptions options) throws org.apache.xmlbeans.XmlException, java.io.IOException {
return (com.example.Address) org.apache.xmlbeans.XmlBeans.getContextTypeLoader().parse( r, type, options ); }
public static com.example.Address parse(javax.xml.stream.XMLStreamReader sr) throws org.apache.xmlbeans.XmlException {
return (com.example.Address) org.apache.xmlbeans.XmlBeans.getContextTypeLoader().parse( sr, type, null ); }
public static com.example.Address parse(javax.xml.stream.XMLStreamReader sr, org.apache.xmlbeans.XmlOptions options) throws org.apache.xmlbeans.XmlException {
return (com.example.Address) org.apache.xmlbeans.XmlBeans.getContextTypeLoader().parse( sr, type, options ); }
public static com.example.Address parse(org.w3c.dom.Node node) throws org.apache.xmlbeans.XmlException {
return (com.example.Address) org.apache.xmlbeans.XmlBeans.getContextTypeLoader().parse( node, type, null ); }
public static com.example.Address parse(org.w3c.dom.Node node, org.apache.xmlbeans.XmlOptions options) throws org.apache.xmlbeans.XmlException {
return (com.example.Address) org.apache.xmlbeans.XmlBeans.getContextTypeLoader().parse( node, type, options ); }
/** @deprecated {@link org.apache.xmlbeans.xml.stream.XMLInputStream} */
public static com.example.Address parse(org.apache.xmlbeans.xml.stream.XMLInputStream xis) throws org.apache.xmlbeans.XmlException, org.apache.xmlbeans.xml.stream.XMLStreamException {
return (com.example.Address) org.apache.xmlbeans.XmlBeans.getContextTypeLoader().parse( xis, type, null ); }
/** @deprecated {@link org.apache.xmlbeans.xml.stream.XMLInputStream} */
public static com.example.Address parse(org.apache.xmlbeans.xml.stream.XMLInputStream xis, org.apache.xmlbeans.XmlOptions options) throws org.apache.xmlbeans.XmlException, org.apache.xmlbeans.xml.stream.XMLStreamException {
return (com.example.Address) org.apache.xmlbeans.XmlBeans.getContextTypeLoader().parse( xis, type, options ); }
/** @deprecated {@link org.apache.xmlbeans.xml.stream.XMLInputStream} */
public static org.apache.xmlbeans.xml.stream.XMLInputStream newValidatingXMLInputStream(org.apache.xmlbeans.xml.stream.XMLInputStream xis) throws org.apache.xmlbeans.XmlException, org.apache.xmlbeans.xml.stream.XMLStreamException {
return org.apache.xmlbeans.XmlBeans.getContextTypeLoader().newValidatingXMLInputStream( xis, type, null ); }
/** @deprecated {@link org.apache.xmlbeans.xml.stream.XMLInputStream} */
public static org.apache.xmlbeans.xml.stream.XMLInputStream newValidatingXMLInputStream(org.apache.xmlbeans.xml.stream.XMLInputStream xis, org.apache.xmlbeans.XmlOptions options) throws org.apache.xmlbeans.XmlException, org.apache.xmlbeans.xml.stream.XMLStreamException {
return org.apache.xmlbeans.XmlBeans.getContextTypeLoader().newValidatingXMLInputStream( xis, type, options ); }
private Factory() { } // No instance of this class allowed
}
}
Ниже приведен источник для класса реализации:
Реализации JAXB создают аннотированные POJO. Созданные классы очень похожи на те, которые мы создали вручную, в сравнении с Simple и XStream .
//
// This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, vJAXB 2.1.10 in JDK 6
// See <a href="http://java.sun.com/xml/jaxb">http://java.sun.com/xml/jaxb</a>
// Any modifications to this file will be lost upon recompilation of the source schema.
// Generated on: 2012.01.23 at 01:19:09 PM EST
//
package com.example;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlType;
/**
* <p>Java class for address complex type.
*
* <p>The following schema fragment specifies the expected content contained within this class.
*
* <pre>
* <complexType name="address">
* <complexContent>
* <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
* <sequence>
* <element name="street" type="{http://www.w3.org/2001/XMLSchema}string"/>
* <element name="city" type="{http://www.w3.org/2001/XMLSchema}string"/>
* </sequence>
* </restriction>
* </complexContent>
* </complexType>
* </pre>
*
*
*/
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "address", propOrder = {
"street",
"city"
})
public class Address {
@XmlElement(required = true)
protected String street;
@XmlElement(required = true)
protected String city;
/**
* Gets the value of the street property.
*
* @return
* possible object is
* {@link String }
*
*/
public String getStreet() {
return street;
}
/**
* Sets the value of the street property.
*
* @param value
* allowed object is
* {@link String }
*
*/
public void setStreet(String value) {
this.street = value;
}
/**
* Gets the value of the city property.
*
* @return
* possible object is
* {@link String }
*
*/
public String getCity() {
return city;
}
/**
* Sets the value of the city property.
*
* @param value
* allowed object is
* {@link String }
*
*/
public void setCity(String value) {
this.city = value;
}
}
В демо-коде мы распаковываем XML-файл, добавляем номер телефона к полученному объекту клиента и затем перенаправляем клиента обратно в XML.
В XMLBeans сгенерированная модель предметной области используется для демарширования (строка 12) и маршала (строка 19). Сгенерированная модель также содержит методы взаимодействия с коллекциями (строка 15), это необходимо, поскольку XMLBeans представляют свойства коллекции в виде массивов.
package com.example;
import java.io.File;
import com.example.CustomerDocument.Customer;
public class Demo {
public static void main(String[] args) throws Exception {
File xml = new File("src/com/example/input.xml");
CustomerDocument customerDocument =
CustomerDocument.Factory.parse(xml);
Customer customer = customerDocument.getCustomer();
PhoneNumber homePhoneNumber = customer.addNewPhoneNumber();
homePhoneNumber.setType("home");
homePhoneNumber.set("555-HOME");
customerDocument.save(System.out);
}
}
JAXB разделяет маршальные / анмаршальные вызовы на стандартные API времени выполнения (строки 9, 13 и 22). Java.util.List используется для свойств коллекции (строка 18).
package com.example;
import java.io.File;
import javax.xml.bind.*;
public class Demo {
public static void main(String[] args) throws Exception {
JAXBContext jc = JAXBContext.newInstance("com.example");
File xml = new File("src/com/example/input.xml");
Unmarshaller unmarshaller = jc.createUnmarshaller();
Customer customer = (Customer) unmarshaller.unmarshal(xml);
PhoneNumber homePhoneNumber = new PhoneNumber();
homePhoneNumber.setType("home");
homePhoneNumber.setValue("555-HOME");
customer.getPhoneNumber().add(homePhoneNumber);
Marshaller marshaller = jc.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
marshaller.marshal(customer, System.out);
}
}
И XMLBeans, и JAXB создают модели Java, которые облегчают разработчикам взаимодействие с XML. Модель JAXB, однако, представляет собой аннотированные POJO, которые имеют следующие преимущества:
- JPA-аннотации могут быть легко применены к модели JAXB, что позволяет модели сохраняться в реляционной базе данных.
- После того, как сгенерированная модель JAXB может быть изменена для обработки изменений в схеме XML, модель XMLBeans необходимо будет восстановить.
- Начиная с Java SE 6, для модели JAXB не требуется никаких дополнительных зависимостей компиляции / времени выполнения.
- Доступно несколько реализаций JAXB: EclipseLink MOXy , Metro , Apache JaxMe и т. Д.
- JAXB — это стандартный уровень привязки для веб-служб JAX-WS (SOAP) и JAX-RS (RESTful).
От http://blog.bdoughan.com/2012/01/how-does-jaxb-compare-to-xmlbeans.html