Статьи

Как JAXB сравнивается с XMLBeans?

В предыдущих статьях я сравнивал JAXB ( JSR-222 ) с Simple и XStream при запуске из объектов Java. В этой статье я буду сравнивать JAXB с XMLBeans при запуске из схемы XML. Я буду использовать XMLBeans 2.5.0 (декабрь 2009), которая является последней версией.

XML-схема (customer.xsd)


Ниже приведена схема 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


Ниже приведен вызов для генерации классов 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
    • Пространство имен / 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
JAXB


Ниже приведен вызов для генерации классов 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
    }
}
AddressImpl

Ниже приведен источник для класса реализации:

/**
 * XML Type:  address
 * Namespace: http://www.example.com
 * Java type: com.example.Address
 *
 * Automatically generated - do not modify.
 */
package com.example.impl;
/**
 * An XML address(@http://www.example.com).
 *
 * This is a complex type.
 */
public class AddressImpl extends org.apache.xmlbeans.impl.values.XmlComplexContentImpl implements com.example.Address
{
    private static final long serialVersionUID = 1L;
     
    public AddressImpl(org.apache.xmlbeans.SchemaType sType)
    {
        super(sType);
    }
     
    private static final javax.xml.namespace.QName STREET$0 =
        new javax.xml.namespace.QName("http://www.example.com", "street");
    private static final javax.xml.namespace.QName CITY$2 =
        new javax.xml.namespace.QName("http://www.example.com", "city");
     
     
    /**
     * Gets the "street" element
     */
    public java.lang.String getStreet()
    {
        synchronized (monitor())
        {
            check_orphaned();
            org.apache.xmlbeans.SimpleValue target = null;
            target = (org.apache.xmlbeans.SimpleValue)get_store().find_element_user(STREET$0, 0);
            if (target == null)
            {
                return null;
            }
            return target.getStringValue();
        }
    }
     
    /**
     * Gets (as xml) the "street" element
     */
    public org.apache.xmlbeans.XmlString xgetStreet()
    {
        synchronized (monitor())
        {
            check_orphaned();
            org.apache.xmlbeans.XmlString target = null;
            target = (org.apache.xmlbeans.XmlString)get_store().find_element_user(STREET$0, 0);
            return target;
        }
    }
     
    /**
     * Sets the "street" element
     */
    public void setStreet(java.lang.String street)
    {
        synchronized (monitor())
        {
            check_orphaned();
            org.apache.xmlbeans.SimpleValue target = null;
            target = (org.apache.xmlbeans.SimpleValue)get_store().find_element_user(STREET$0, 0);
            if (target == null)
            {
                target = (org.apache.xmlbeans.SimpleValue)get_store().add_element_user(STREET$0);
            }
            target.setStringValue(street);
        }
    }
     
    /**
     * Sets (as xml) the "street" element
     */
    public void xsetStreet(org.apache.xmlbeans.XmlString street)
    {
        synchronized (monitor())
        {
            check_orphaned();
            org.apache.xmlbeans.XmlString target = null;
            target = (org.apache.xmlbeans.XmlString)get_store().find_element_user(STREET$0, 0);
            if (target == null)
            {
                target = (org.apache.xmlbeans.XmlString)get_store().add_element_user(STREET$0);
            }
            target.set(street);
        }
    }
     
    /**
     * Gets the "city" element
     */
    public java.lang.String getCity()
    {
        synchronized (monitor())
        {
            check_orphaned();
            org.apache.xmlbeans.SimpleValue target = null;
            target = (org.apache.xmlbeans.SimpleValue)get_store().find_element_user(CITY$2, 0);
            if (target == null)
            {
                return null;
            }
            return target.getStringValue();
        }
    }
     
    /**
     * Gets (as xml) the "city" element
     */
    public org.apache.xmlbeans.XmlString xgetCity()
    {
        synchronized (monitor())
        {
            check_orphaned();
            org.apache.xmlbeans.XmlString target = null;
            target = (org.apache.xmlbeans.XmlString)get_store().find_element_user(CITY$2, 0);
            return target;
        }
    }
     
    /**
     * Sets the "city" element
     */
    public void setCity(java.lang.String city)
    {
        synchronized (monitor())
        {
            check_orphaned();
            org.apache.xmlbeans.SimpleValue target = null;
            target = (org.apache.xmlbeans.SimpleValue)get_store().find_element_user(CITY$2, 0);
            if (target == null)
            {
                target = (org.apache.xmlbeans.SimpleValue)get_store().add_element_user(CITY$2);
            }
            target.setStringValue(city);
        }
    }
     
    /**
     * Sets (as xml) the "city" element
     */
    public void xsetCity(org.apache.xmlbeans.XmlString city)
    {
        synchronized (monitor())
        {
            check_orphaned();
            org.apache.xmlbeans.XmlString target = null;
            target = (org.apache.xmlbeans.XmlString)get_store().find_element_user(CITY$2, 0);
            if (target == null)
            {
                target = (org.apache.xmlbeans.XmlString)get_store().add_element_user(CITY$2);
            }
            target.set(city);
        }
    }
}
Модель Java — JAXB

Реализации 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

В 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

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