Ответ 1
Вы можете передать этот объект в Unmarshaller.unmarshal(Node)
, он должен иметь возможность его отменить.
Веб-служба возвращает объект, определенный 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 com.districthp.core.server.ws.alliance.AllianceApi getRates SEVERE: com.sun.org.apache.xerces.internal.dom.ElementNSImpl не может быть отброшен com.districthp.core.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);
Вы можете передать этот объект в Unmarshaller.unmarshal(Node)
, он должен иметь возможность его отменить.
Вы можете использовать @XmlAnyElement(lax=true)
. Это преобразует XML с известными корневыми элементами (@XmlRootElement
или @XmlElementDecl
) в объекты домена. Пример:
Из того, что я нашел при работе с XML, anyType
может представлять любой объект, поэтому ближайшая вещь, на которую вы можете перевести его, равна java.lang.Object
. (Помимо того, что anyType
может технически быть дырой в безопасности, позволяя кому-то вводить что-нибудь, в том числе вредоносную двоичную информацию, в это место, и ничто не остановит его, так как ваша схема позволяет это.)
Лучше всего изменить свою схему, чтобы можно было сопоставить свой пользовательский объект. Это чище как с точки зрения программирования, так и с точки зрения потребления, и с точки зрения безопасности.
Пока вы не можете этого сделать, я бы рекомендовал сохранить этот тип как атрибут вашего элемента. Возможно, вам потребуется написать собственный код, чтобы помочь вам преобразовать anyType
обратно в этот объект, но по крайней мере вы знаете его тип.
Мои два цента основаны на моем опыте (в основном в сфере интеграции).