XSD/JAXB: последовательность нескольких элементов, ограниченных элементами с одинаковым именем



Мой элемент модели может содержать несколько дочерних элементов различных типов. Для каждого типа может присутствовать только 0 или 1 дочерний элемент. Порядок этих элементов определен, т. е. все элементы типа A стоят перед B и т. д. Поэтому мой класс модели, созданный JAXB, должен иметь отдельное свойство getter / setter для каждого типа дочернего элемента.



Что усложняет дело, так это одно исключение из вышеприведенного правила: в начале и ближе к концу списка дочерних элементов может быть каждый из них содержит 0 или 1 элемент типа X, и оба эти элемента имеют одинаковое имя.



Вот немного упрощенная версия моего текущего реального типа XSD:



<xs:complexType name="Activity">
<xs:sequence>
<xs:element name="log" type="DiagnosticLogMessage" minOccurs="0" maxOccurs="1" />
<xs:element name="inputs" type="Mappings" minOccurs="0" maxOccurs="1" />
<xs:element name="outputs" type="Mappings" minOccurs="0" maxOccurs="1" />
<xs:element name="log" type="DiagnosticLogMessage" minOccurs="0" maxOccurs="1" />
<xs:element name="to" type="DirectConnection" minOccurs="0" maxOccurs="1" />
</xs:sequence>
</xs:complexType>


"лог" - это проблемный элемент. При приведенном выше определении типа " to " правильно получает свое собственное свойство, но остальные элементы переходят в список с именем "logsAndInputsAndOutputs". Если я переименую два элемента" log " в "logBefore" и "logAfter", каждый элемент получит свое собственное свойство, поэтому ясно, что проблема заключается в том, что JAXB не может различать два " log " s.



Я понимаю, что сам XSD не совсем точен: он допускает единственный дочерний элемент типа "log", и в этом случае он не определен, следует ли считать его элементом" до "или" после". В моем текущем (написанном вручную) классе чтения у меня есть явный код для обнаружения этого случая и интерпретации одного элемента "log" как элемента "before".



Я ищу способ сказать JAXB, чтобы он по-разному относился к двум элементам "log"., либо через xjb сопоставлений или, возможно, с более конкретным в XSD.

604   1  

1 ответ:

Примечание: я EclipseLink JAXB (MOXy) ведущий и член группы JAXB (JSR-222) экспертная группа.

Ниже показано, как вы можете справиться с этим вариантом использования, используя расширение MOXy @XmlPath.

XML Schema (схема.xsd)

Вот схема XML, основанная на фрагменте, который вы предоставили в своем вопросе.

<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
    targetNamespace="urn:forum17408865" xmlns="urn:forum17408865"
    elementFormDefault="qualified">

    <xs:element name="foo">
        <xs:complexType>
            <xs:sequence>
                <xs:element name="bar" type="Activity"/>
            </xs:sequence>
        </xs:complexType>
    </xs:element>

    <xs:complexType name="Activity">
        <xs:sequence>
            <xs:element name="log" type="DiagnosticLogMessage"
                minOccurs="0" maxOccurs="1" />
            <xs:element name="inputs" type="Mappings" minOccurs="0"
                maxOccurs="1" />
            <xs:element name="outputs" type="Mappings" minOccurs="0"
                maxOccurs="1" />
            <xs:element name="log" type="DiagnosticLogMessage"
                minOccurs="0" maxOccurs="1" />
            <xs:element name="to" type="DirectConnection" minOccurs="0"
                maxOccurs="1" />
        </xs:sequence>
    </xs:complexType>

    <xs:complexType name="DiagnosticLogMessage" />

    <xs:complexType name="Mappings" />

    <xs:complexType name="DirectConnection" />

</xs:schema>

Деятельность

MOXy имеет расширение @XmlPath, которое позволяет сопоставлять с XML элемент, основанный на его положении. Этот класс не может быть создан из XML-схемы, поэтому мы создадим его сами.

package forum17408865;

import javax.xml.bind.annotation.*;
import org.eclipse.persistence.oxm.annotations.XmlPath;

@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(propOrder={"log1", "inputs", "outputs", "log2", "to"})
public class Activity {

    @XmlPath("log[1]")
    private DiagnosticLogMessage log1;

    private Mappings inputs;

    private Mappings outputs;

    @XmlPath("log[2]")
    private DiagnosticLogMessage log2;

    private DirectConnection to;

}

Связывание.xml

Чтобы JAXB использовал класс, который мы создали вручную, мы будем использовать файл Привязок JAXB.

<jxb:bindings xmlns:xs="http://www.w3.org/2001/XMLSchema"
    xmlns:jxb="http://java.sun.com/xml/ns/jaxb" version="2.1">

    <jxb:bindings schemaLocation="schema.xsd">
        <jxb:bindings node="//xs:complexType[@name='Activity']">
            <jxb:class ref="forum17408865.Activity" />
        </jxb:bindings>
    </jxb:bindings>

</jxb:bindings>

Вызов XJC

Ниже приведен вызов XJC, который использует файл Привязок. Обратите внимание, что нам также нужно было использовать флаг -nv, чтобы отключить проверку схемы.

xjc -nv -b binding.xml schema.xs

Для Большего Информация

Comments

    Ничего не найдено.