Unmarshalling с использованием JAXB для коллекций

65
4

У меня есть XML, который выглядит так:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<layout>
<panel>
<ComboBox incEmpty="true">
<label>Shipment Types:</label>
<fieldName>StringData1</fieldName>
<type>static</type>
<element>Samples</element>
<element>Gifts</element>
<element>Possessions</element>
<element>Merchandise</element>
</ComboBox>
<CheckBox>
<label>Report Usage:</label>
<fieldName>IntData1</fieldName>
</CheckBox>
</panel>
</layout>

В принципе мне нужно создать панель Swing из XML. Будет несколько вхождений <ComboBox> и <CheckBox>. Мне нужно получить их в том порядке, в котором они были добавлены в XML, чтобы я мог отображать их на экране в правильном порядке. Мне нужно развязать этот XML и сгенерировать код. Я не могу придумать XSD, который создаст мне правильные классы, чтобы заставить это работать. Я знаю, что мне понадобится коллекция, чтобы иметь возможность заказать предметы в правильном порядке. К этому я создал обновленный XML:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<layout>
<panel>
<component>
<ComboBox incEmpty="true">
<label>Shipment Types:</label>
<fieldName>StringData1</fieldName>
<type>static</type>
<element>Samples</element>
<element>Gifts</element>
<element>Possessions</element>
<element>Merchandise</element>
</ComboBox>
</component>
<component>
<CheckBox>
<label>Report Usage:</label>
<fieldName>IntData1</fieldName>
</CheckBox>
</component>
</panel>
</layout>

Идея заключалась в том, что я мог бы программно сделать Component в качестве интерфейса и сделать что-то в своих ComboBox implements Component и CheckBox implements Component а затем в Panel что-то вроде:

public List<Component> getComponent() {
if (component == null) {
component = new ArrayList<Component>();
}
return this.component;
}

Затем я мог проверить каждый элемент в коллекции для типа (instanceof) и обработать его соответствующим образом. Однако JAXB, похоже, не очень хорошо справляется с интерфейсами. Я попытался использовать описанный здесь сценарий: как обернуть подсписку с помощью jaxb, но мне это не подходит, поскольку мне нужно возвращать разные объекты как часть одной коллекции.

Любая помощь будет высоко ценится. Я могу отправить xsds здесь, если это необходимо.

спросил(а) 2021-01-19T13:46:04+03:00 9 месяцев, 1 неделя назад
1
Решение
65

Вы можете использовать структуру choice в своей XML-схеме, это приведет к созданию аннотации, подобной следующей. Это означает, что если встречается элемент ComboBox или CheckBox он помещается в коллекцию component.

@XmlElements({
@XmlElement(name="ComboBox", type=ComboBox.class),
@XmlElement(name="CheckBox", type="CheckBox.class)
})
public List<Component> getComponent() {
if (component == null) {
component = new ArrayList<Component>();
}
return this.component;
}

Чтобы получить больше информации

ответил(а) 2021-01-19T13:46:04+03:00 9 месяцев, 1 неделя назад
47

Спасибо Блейзу за то, что он указал мне в правильном направлении. Большое спасибо. Это xsd. Я закончил:

<?xml version="1.0" encoding="UTF-8"?>
<xsd:schema attributeFormDefault="qualified" elementFormDefault="qualified" version="1.0" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<xsd:element name="layout" type="layout" />
<xsd:complexType name="layout">
<xsd:sequence>
<xsd:element name="panel" type="panel" />
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="panel">
<xsd:sequence>
<xsd:choice>
<xsd:element name="ComboBox" type="ComboBox" maxOccurs="unbounded" />
<xsd:element name="CheckBox" type="CheckBox" maxOccurs="unbounded" />
<xsd:element name="InputBox" type="InputBox" maxOccurs="unbounded"/>
</xsd:choice>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="ComboBox">
<xsd:sequence>
<xsd:element name="label" type="xsd:string" />
<xsd:element name="fieldName" type="xsd:string" />
<xsd:element name="type" type="xsd:string" />
<xsd:element maxOccurs="unbounded" name="element" type="xsd:string" />
</xsd:sequence>
<xsd:attribute name="incEmpty" type="xsd:boolean" />
</xsd:complexType>
<xsd:complexType name="CheckBox">
<xsd:sequence>
<xsd:element name="label" type="xsd:string" />
<xsd:element name="fieldName" type="xsd:string" />
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="InputBox">
<xsd:sequence>
<xsd:element name="label" type="xsd:string" />
<xsd:element name="fieldName" type="xsd:string" />
<xsd:element name="type" type="xsd:string" />
</xsd:sequence>
</xsd:complexType>
</xsd:schema>

Затем в моем классе Panel у меня есть:


    @XmlElements({
@XmlElement(name = "ComboBox", type = ComboBox.class),
@XmlElement(name = "CheckBox", type = CheckBox.class),
@XmlElement(name = "InputBox", type = InputBox.class)
})
protected List<MyComponent> component;
...
...
public List<MyComponent> getComponent() {
if (component == null) {
component = new ArrayList<MyComponent>();
}
return this.component;
}

Это, наряду с базовым интерфейсом MyComponent который затем реализуется моими соответствующими классами CheckBox, ComboBox, InputBox позволяет мне получить результат, который я получил после. Еще раз спасибо, Блейз

ответил(а) 2021-01-19T13:46:04+03:00 9 месяцев, 1 неделя назад
Ваш ответ
Введите минимум 50 символов
Чтобы , пожалуйста,
Выберите тему жалобы:

Другая проблема