XSD элементы с базовым типом - PullRequest
1 голос
/ 31 марта 2012

Как в схеме XSD сделать последовательность элементов с разными именами и одним базовым типом?

<function name="test">
    <set name="name" value="StackMommy" />
    <log message="hello, ${name}" />
</function>

Я хочу с сгенерированными jaxb классами pojo вот так:

class Function {
    List<Command> commands;
}

1 Ответ

2 голосов
/ 31 марта 2012

Аннотация @XmlElementRef - это то, что вы ищете в этом случае использования. Он используется для отображения концепции групп замещения.

Функция

Свойство commands помечено @XmlElementRef. Это означает, что мы будем заполнять это свойство на основе возникающих элементов XML, связанных с подклассами Command либо @XmlRootElement, либо @XmlElementDecl.

package forum9952449;

import java.util.List;
import javax.xml.bind.annotation.*;

@XmlRootElement
class Function {
    @XmlElementRef
    List<Command> commands;
}

Команда

Аннотация @XmlSeeAlso используется для указания на подклассы. Это не обязательный шаг, но это означает, что нам не нужно явно передавать подклассы при загрузке JAXBContext.

package forum9952449;

import javax.xml.bind.annotation.XmlSeeAlso;

@XmlSeeAlso({Set.class, Log.class})
public abstract class Command {

}

Установить

Нам нужно пометить этот класс @XmlRootElement. В этом случае имя корневого элемента по умолчанию равно set.

package forum9952449;

import javax.xml.bind.annotation.*;

@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public class Set extends Command {

    @XmlAttribute
    private String name;

    @XmlAttribute
    private String value;

}

Вход

Мы снова пометили этот подкласс @XmlRootElement.

package forum9952449;

import javax.xml.bind.annotation.*;

@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public class Log extends Command {

    @XmlAttribute
    private String message;

}

Демо

package forum9952449;

import java.io.File;
import javax.xml.bind.*;

public class Demo {

    public static void main(String[] args) throws Exception {
        JAXBContext jc = JAXBContext.newInstance(Function.class);

        File xml = new File("src/forum9952449/input.xml");
        Unmarshaller unmarshaller = jc.createUnmarshaller();
        Function function = (Function) unmarshaller.unmarshal(xml);

        Marshaller marshaller = jc.createMarshaller();
        marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
        marshaller.marshal(function, System.out);
    }

}

Вход / выход

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<function>
    <set value="StackMommy" name="name"/>
    <log message="hello, ${name}"/>
</function>

function.xsd

Соответствующая XML-схема будет выглядеть примерно так: Поскольку вы можете начать с объектной модели с JAXB, вам это не нужно.

<xs:schema version="1.0" xmlns:xs="http://www.w3.org/2001/XMLSchema">

    <xs:element name="function" type="function"/>

    <xs:element name="command" type="command"/>

    <xs:element name="set" type="set"
        substitutionGroup="command"/>

    <xs:element name="log" type="log"
        substitutionGroup="command"/>

    <xs:complexType name="function">
        <xs:sequence>
            <xs:element ref="command"/>
        </xs:sequence>
    </xs:complexType>

    <xs:complexType name="command" abstract="true">
        <xs:sequence/>
    </xs:complexType>

    <xs:complexType name="set">
        <xs:complexContent>
            <xs:extension base="command">
                <xs:attribute name="name" type="xs:string"/>
                <xs:attribute name="value" type="xs:string"/>
            </xs:extension>
        </xs:complexContent>
    </xs:complexType>

    <xs:complexType name="log">
        <xs:complexContent>
            <xs:extension base="command">
                <xs:attribute name="message"/>
            </xs:extension>
        </xs:complexContent>
    </xs:complexType>

</xs:schema>

Для получения дополнительной информации

...