Статьи

Использование JAXB для генерации XML из XSD

Это сообщение было опубликовано Мохамедом Санауллой из Experiences Unlimited , нашего последнего партнера JCG . Мохамед объясняет, как использовать JAXB для генерации XML из заданного XSD .

(ПРИМЕЧАНИЕ: оригинальный пост был слегка отредактирован для улучшения читабельности)

Мы можем использовать JAXB для преобразования объектов Java в XML с использованием заданной схемы и, наоборот, для преобразования XML в объекты Java. Схема XML может быть указана в DTD , XSD или другом формате.

Инструмент «xjc» можно использовать для генерации аннотированных классов Java из схемы XSD. Можно загрузить пакет разработчика веб-служб Java (WSDP) , в него входят необходимые инструменты реализации JAXB. Здесь я расскажу, как динамически генерировать XML.

Пример используемого XSD:

— расход.xsd

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
<?xml version="1.0"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="expenseReport" type="ExpenseT" />
<xs:complexType name="ExpenseT">
    <xs:sequence>
        <xs:element name="user" type="UserT"/>
        <xs:element name="items" type="ItemListT"/>
    </xs:sequence>
</xs:complexType>
<xs:complexType name="UserT">
    <xs:sequence>
        <xs:element name="userName" type="xs:string" />
    </xs:sequence>
</xs:complexType>
<xs:complexType name="ItemListT">
     <xs:sequence>
         <xs:element name="item" type="ItemT" maxOccurs="unbounded"/>
     </xs:sequence>
</xs:complexType>
<xs:complexType name="ItemT">
     <xs:sequence>
         <xs:element name="itemName" type="xs:string" />
         <xs:element name="purchasedOn" type="xs:string" />
         <xs:element name="amount" type="xs:decimal" />
     </xs:sequence>
</xs:complexType>
</xs:schema>

Теперь мы используем инструмент xjc для генерации соответствующих классов Java. Сгенерированные Java-классы соответствующим образом аннотированы. Я не буду вдаваться в подробности аннотации классов, потому что это усложнит ситуацию.

xjc.exe расход.xsd

По умолчанию команда генерирует классы Java в каталоге с именем «генерируется». Есть много опций, которые можно использовать с xjc, и можно взглянуть на использование

xjc -help

Класс Main ниже использует сгенерированные классы для создания XML.

— Main.java

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
package generated;
  
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBElement;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import java.math.BigDecimal;
  
public class Main
  
{
    public static void main(String[] args) throws JAXBException
    {
  
        ObjectFactory factory = new ObjectFactory();
  
        UserT user = factory.createUserT();
        user.setUserName("Sanaulla");
        ItemT item = factory.createItemT();
        item.setItemName("Seagate External HDD");
        item.setPurchasedOn("August 24, 2010");
        item.setAmount(new BigDecimal("6776.5"));
  
        ItemListT itemList = factory.createItemListT();
        itemList.getItem().add(item);
  
        ExpenseT expense = factory.createExpenseT();
        expense.setUser(user);
        expense.setItems(itemList);
  
        JAXBContext context = JAXBContext.newInstance("generated");
        JAXBElement<ExpenseT> element = factory.createExpenseReport(expense);
        Marshaller marshaller = context.createMarshaller();
        marshaller.setProperty("jaxb.formatted.output",Boolean.TRUE);
        marshaller.marshal(element,System.out);
    }
  
}

В приведенном выше XSD мы видим, что объявлено несколько сложных типов. Эти сложные типы генерируются в классах Java. Дочерние элементы и атрибуты становятся свойствами класса, и им предоставляются методы получения и установки. Нельзя напрямую создать экземпляр таких классов, то есть нельзя вызывать для них новые. Всякий раз, когда мы компилируем XSD, генерируется класс ObjectFactory — это фабрика для создания экземпляров сложных типов XSD (строки 17, 19, 24, 27 в приведенном выше классе Java).

Получив экземпляр, мы заполняем свойства соответствующими данными, используя установщики, предоставляемые классом. Также обратите внимание, что сложный элемент может иметь много сложных элементов в качестве членов класса. В этом случае мы используем фабрику, чтобы получить экземпляр сложных элементов, а затем используем установщики внешнего сложного элемента.

Например: в приведенном выше XSD ExpenseT является сложным типом, который состоит из UserT и списка ItemT (ItemListT). В приведенном выше Java-классе (строки 27, 28, 29) мы создаем экземпляр ExpenseT, а затем используем установщики для установки значений UserT и ItemListT. RootElement создается путем вызова createExpenseReport () для фабрики. На имя метода влияют имя корневого элемента и тип возвращаемого значения, а также тип аргумента метода такой же, как и у типа корневого элемента.

После того, как мы установили значения для различных элементов, атрибутов, которые должны входить в XML, пришло время фактически генерировать XML. У нас должен быть Marshaller (для получения XML из объектов Java) или Unmarshaller (для получения объектов Java из XML).

Нам нужен маршаллер, который можно получить из экземпляра JAXBContext . Строки 31,32 получают экземпляр Marshaller. Для маршаллера могут быть установлены разные свойства, и в приведенном выше коде мы устанавливаем jaxb.formatted.output как true, что означает, что полученный XML-файл аккуратно отформатирован, что делает его читаемым для пользователя.

Различные поддерживаемые свойства:

  • jaxb.encoding
  • jaxb.formatted.output
  • jaxb.schemaLocation
  • jaxb.noNamespaceSchemaLocation
  • jaxb.fragment

<instance_of_marshaller> .marshal () — это метод, используемый для генерации XML. Его перегружают, чтобы принять следующие механизмы вывода:

Сгенерированный XML показан ниже:

01
02
03
04
05
06
07
08
09
10
11
12
13
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
  <expenseReport>
    <user>
      <userName>Sanaulla</userName>
   </user>
   <items>
     <item>
       <itemName>Seagate External HDD</itemName>
       <purchasedOn>August 24, 2010</purchasedOn>
       <amount>6776.5</amount>
     </item>
   </items>
</expenseReport>

Статьи по Теме: