Как создать java-объект из anyType, возвращенного из службы, с помощью JAXB?

Веб-служба возвращает объект, определенный WSDL как:

<s:complexType mixed="true"><s:sequence><s:any/></s:sequence></s:complexType>

Когда я распечатываю информацию о классе этого объекта, она выглядит так:

class com.sun.org.apache.xerces.internal.dom.ElementNSImpl

Но мне нужно разобрать этот объект как объект следующего класса:

@XmlAccessorType(XmlAccessType.FIELD) 
@XmlType(name = "", propOrder = {
        "info",
        "availability",
        "rateDetails",
        "reservation",
        "cancellation",
        "error" }) 
@XmlRootElement(name = "ArnResponse") 
public class ArnResponse { }

Я знаю, что ответ правильный, так как я знаю, как упорядочить XML этого объекта:

Marshaller m = jc.createMarshaller();
m.setProperty( Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE );
m.marshal(rootResponse, System.out);

Что распечатывает:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<ns2:SubmitRequestDocResponse xmlns:ns2="http://tripauthority.com/hotel">
    <ns2:SubmitRequestDocResult>
        <!-- below is the object I'm trying to unmarshall -->
        <ArnResponse>
            <Info />
            <Availability>
                <!-- etc--> 
             </Availability>
        </ArnResponse>
    </ns2:SubmitRequestDocResult>
</ns2:SubmitRequestDocResponse>

Как я могу превратить объект ElementNSImpl, который я вижу, в объект ArnResponse, который, как я знаю, он представляет?

Кроме того, я использую AppEngine, где доступ к файлам ограничен.

Спасибо за любую помощь

Обновление:

Я добавил аннотацию @XmlAnyElement(lax=true), например:

  @XmlAccessorType(XmlAccessType.FIELD)
  @XmlType(name = "", propOrder = {
      "content"
  })
  @XmlSeeAlso(ArnResponse.class)
  public static class SubmitRequestDocResult {

    @XmlMixed
    @XmlAnyElement(lax = true)
    protected List<Object> content;

Но это не имеет никакого значения.

Это как-то связано с тем, что содержание List?

Вот код, в котором я пытаюсь получить доступ к содержимому после его возврата с сервера:

List list = rootResponse.getSubmitRequestDocResult().getContent();

for (Object o : list) {
  ArnResponse response = (ArnResponse) o;
  System.out.println(response);
}

Что имеет выход:

31 января 2012 г., 10:04:14. .server.ws.alliance.response.ArnResponse

Ответ:

ответ axtavt сделал свое дело. Это сработало:

Object content = ((List)result.getContent()).get(0);
JAXBContext context = JAXBContext.newInstance(ArnResponse.class);
Unmarshaller um = context.createUnmarshaller();
ArnResponse response = (ArnResponse)um.unmarshal((Node)content);
System.out.println("response: " + response);

person Cuga    schedule 31.01.2012    source источник
comment
У меня есть копии всех схем для объектов ответа и WSDL, если вам это поможет.   -  person Cuga    schedule 31.01.2012
comment
Обратите внимание, что здесь используется Node org.w3c.dom.Node.   -  person Mike Partridge    schedule 12.06.2013


Ответы (3)


Вы можете передать этот объект Unmarshaller.unmarshal(Node), он должен иметь возможность его демаршалировать.

person axtavt    schedule 31.01.2012

Вы можете использовать @XmlAnyElement(lax=true). Это преобразует XML с известными корневыми элементами (@XmlRootElement или @XmlElementDecl) в объекты домена. Для примера см.:

person bdoughan    schedule 31.01.2012
comment
Я проверил, но аннотация уже была там. Пожалуйста, взгляните на мой обновленный вопрос. Еще раз спасибо за вашу помощь, и я уже встречал ваш блог и другие ваши ответы здесь, на SO. Ваша работа мне уже очень помогла. - person Cuga; 31.01.2012

Из того, что я обнаружил при работе с XML, anyType может представлять любой объект, поэтому самое близкое, что вы можете отобразить, это java.lang.Object. (Помимо того факта, что anyType технически может быть дырой в безопасности, позволяющей кому-то внедрить что угодно, включая вредоносный двоичный файл, в это место, и ничто не остановит его, поскольку ваша схема это позволяет.)

Лучше всего изменить схему, чтобы разрешить сопоставление с вашим пользовательским объектом. Это чище как с точки зрения программирования, так и с точки зрения потребления и с точки зрения безопасности.

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

Мои пять копеек основаны на моем опыте (в основном в сфере интеграции).

person Chris Aldrich    schedule 31.01.2012
comment
Да, если бы я мог, я бы не использовал anyType, но мы интегрируемся с чужой схемой, так что мы с ней застряли. - person Cuga; 31.01.2012