23.09.2012

Автоматизация маппинга XML - Java.

Я уже упоминал об одном из способов связывания Java классов с их XML представлением - JAXB. Если стоит задача создания структуры Java классов для преобразования данных из XML документа заданного формата с помощью JAXB, то для этого обычно используется утилита jaxb-xjc (Java Architecture for XML Binding Binding Compiler): достаточно иметь XSD файл со схемой документа, чтобы сгенерировать структуру классов. А что если схемы нет, а есть только пример самого XML документа? Конечно, ничто не мешает создать классы для JAXB вручную, но если исходные XML данные сложны по структуре и велики по объему - то зачастую это может оказаться лишней тратой времени. С помощью утилиты trang можно создать схему на основе примера XML. Допустим есть такой XML файл и нам нужно создать соответствующие ему Java классы для JAXB: example.xml:
<data type="dictionaries">
 <dictionary name="buildings">
 <itemnum>2</itemnum>
 <comment>Buildings</comment>
 <element>
  <id>0</id>
  <name>building 1</name>
  <cost>10000.50</cost>
 </element>
 <element>
  <id>1</id>
  <name>building 2</name>
  <cost>20000.50</cost>
 </element>
 </dictionary>
</data>

Создадим XML схему с помощью trang:

$ java -jar ./trang.jar ./example.xml ./schema.xsd  

В результате получится такой .xsd файл: schema.xsd:

<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
elementFormDefault="qualified">
  <xs:element name="data">
    <xs:complexType>
      <xs:sequence>
        <xs:element ref="dictionary"/>
      </xs:sequence>
      <xs:attribute name="type" use="required" type="xs:NCName"/>
    </xs:complexType>
  </xs:element>
  <xs:element name="dictionary">
    <xs:complexType>
      <xs:sequence>
        <xs:element ref="itemnum"/>
        <xs:element ref="comment"/>
        <xs:element maxOccurs="unbounded" ref="element"/>
      </xs:sequence>
      <xs:attribute name="name" use="required" type="xs:NCName"/>
    </xs:complexType>
  </xs:element>
  <xs:element name="itemnum" type="xs:integer"/>
  <xs:element name="comment" type="xs:NCName"/>
  <xs:element name="element">
    <xs:complexType>
      <xs:sequence>
        <xs:element ref="id"/>
        <xs:element ref="name"/>
        <xs:element ref="cost"/>
      </xs:sequence>
    </xs:complexType>
  </xs:element>
  <xs:element name="id" type="xs:integer"/>
  <xs:element name="name" type="xs:string"/>
  <xs:element name="cost" type="xs:decimal"/>
</xs:schema>

Посмотрим на получившуюся схему документа в визуальном представлении:

Выглядит неплохо, теперь осталось сгенерировать на основе этой схемы классы:

$ java -jar ./jaxb-xjc.jar ./schema.xsd

Все готово, с помощью jaxb-xjc была создана необходимая структура классов: Data.java, Dictionary.java и Element.java.

Data.java:

@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "", propOrder = {
    "dictionary"
})
@XmlRootElement(name = "data")
public class Data {

    @XmlElement(required = true)
    protected Dictionary dictionary;
    @XmlAttribute(name = "type", required = true)
    @XmlJavaTypeAdapter(CollapsedStringAdapter.class)
    @XmlSchemaType(name = "NCName")
    protected String type;
   
    public Dictionary getDictionary() {
        return dictionary;
    }
    public void setDictionary(Dictionary value) {
        this.dictionary = value;
    }
    public String getType() {
        return type;
    }
    public void setType(String value) {
        this.type = value;
    }
}


Теги: jaxb java programming xml

comments powered by Disqus