Как мне сопоставить несколько элементов в один класс в JAXB - PullRequest
2 голосов
/ 12 сентября 2011

У меня есть следующий XML на входе:

<root>
 <response1></response1>
</root>

или

<root>
 <response2></response2>
</root>

И, возможно, существует множество тегов ответов, каждый из которых мне нужно сопоставить с одним классом Response, поскольку они имеют почти одинаковую структуру.

Легко ли это сделать в JAXB?

Спасибо.

Ответы [ 5 ]

5 голосов
/ 12 сентября 2011

Это можно сделать с помощью аннотации @XmlElements:

@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public class Root {

    @XmlElements({
        @XmlElement(name="response1", type=Response.class),
        @XmlElement(name="response2", type=Response.class),
        @XmlElement(name="response3", type=Response.class)
    })
    private Response response;

}
2 голосов
/ 12 сентября 2011

Я заставил это работать таким образом. Он использует XMLStreamReader в качестве источника и StreamReaderDelegate для перехвата и перезаписи имен элементов до того, как они достигнут jaxb.

Основной тестовый класс:

package grimbo.test.jaxb;

import java.io.ByteArrayInputStream;
import java.io.InputStream;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Unmarshaller;
import javax.xml.namespace.QName;
import javax.xml.stream.FactoryConfigurationError;
import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamReader;
import javax.xml.stream.util.StreamReaderDelegate;

public class JaxbTest {
    public static <T> T unmarshal(Class<T> clazz, InputStream inputStream) throws JAXBException, XMLStreamException,
            FactoryConfigurationError {
        XMLStreamReader r = XMLInputFactory.newInstance().createXMLStreamReader(inputStream);
        MyXMLStreamReader my = new MyXMLStreamReader(r);
        String packageName = clazz.getPackage().getName();
        JAXBContext jc = JAXBContext.newInstance(packageName);
        Unmarshaller u = jc.createUnmarshaller();
        return (T) u.unmarshal(my);
    }

    public static void main(String[] args) throws Exception {
        String xml1 = "<root>" + "<response1>test1</response1>" + "</root>";
        String xml2 = "<root>" + "<response2>test2</response2>" + "</root>";

        Object ob = unmarshal(Response.class, new ByteArrayInputStream(xml1.getBytes()));
        System.out.println(ob);

        ob = unmarshal(Response.class, new ByteArrayInputStream(xml2.getBytes()));
        System.out.println(ob);
    }

    static class MyXMLStreamReader extends StreamReaderDelegate {
        public MyXMLStreamReader(XMLStreamReader reader) {
            super(reader);
        }

        public QName getName() {
            QName qname = super.getName();
            return qname;
        }

        public String getLocalName() {
            String localName = super.getLocalName();
            if (localName.matches("response\\d+")) {
                return "response";
            }
            return localName;
        }
    }
}

Класс Response:

package grimbo.test.jaxb;

import javax.xml.bind.annotation.XmlRootElement;

@XmlRootElement(name = "root", namespace = "")
public class Response {
    String response;

    public String getResponse() {
        return response;
    }

    public void setResponse(String response) {
        this.response = response;
    }

    @Override
    public String toString() {
        return "Response [response=" + response + "]";
    }
}

И в этом пакете также есть файл jaxb.index, который объявляет класс Response:

Response

Результат теста:

Response [response=test1]
Response [response=test2]

Это какая-то помощь?

2 голосов
/ 12 сентября 2011

Ну, конечно.В файле XSD сначала определите тип:

<xs:complexType name="response">
  <!-- define type here -->
</xs:complexType>

Теперь определите элементы, используя его:

<xs:element name="response1" type="response"/>
<xs:element name="response2" type="response"/>
<!-- and so on and so forth -->
1 голос
/ 12 сентября 2011

Самое простое, что можно сделать в imo, - это сделать элемент ответа неограниченным списком в вашей схеме, и после того, как вы создадите привязки, вы можете перебирать список узлов ответа.

0 голосов
/ 14 июля 2013

Я попытался отобразить несколько тегов в один класс, используя JAXB с тем же форматом, упомянутым выше.Теперь определите ваши элементы, используя его:

<xs:element name="response1" type="response"/>
<xs:element name="response2" type="response"/>
<!-- and so on and so forth -->

While unmarshalling JAXB validates the XML(format) with response class  format mentioned in XSD file ,but its is giving me JAXB.element class object instead of response object.

Please suugest with answer.. 
...