В предыдущих статьях я сравнивал 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