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.
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