JAXB unmarshall с пространствами имен и префиксом
Я использую JAXB для синтаксического анализа элементов XML из ответа SOAP. Я определил классы POJO для элементов xml. Я тестировал классы pojo без пространства имен и префикс его рабочего штрафа. Однако, когда я пытаюсь проанализировать пространства имен и префикс, обращенные к следующему исключению. Требование состоит в анализе ввода из объекта SOAPMessage
javax.xml.bind.UnmarshalException: unexpected element (uri:"http://schemas.xmlsoap.org/soap/envelope/", local:"Envelope"). Expected elements are <{}Envelope>
Попробовал исправить, создав @XMLSchema для пакета в package-info.java и разместив этот файл в папке пакета. Может ли кто-нибудь из вас направлять меня для продвижения вперед?
Написал это сообщение, но не помог мне.
EDITED: XMLSchema
@javax.xml.bind.annotation.XmlSchema (
xmlns = { @javax.xml.bind.annotation.XmlNs(prefix = "env",
namespaceURI="http://schemas.xmlsoap.org/soap/envelope/"),
@javax.xml.bind.annotation.XmlNs(prefix="ns3", namespaceURI="http://www.xxxx.com/ncp/oomr/dto/")
}
)
package com.one.two;
Заранее спасибо
Ответы
Ответ 1
Это можно сделать без изменения сгенерированного кода JAXB с использованием стандартного класса SOAPMessage. Я написал об этом здесь и здесь
Немного неудобно, но работает правильно.
Ранжирование
Farm farm = new Farm();
farm.getHorse().add(new Horse());
farm.getHorse().get(0).setName("glue factory");
farm.getHorse().get(0).setHeight(BigInteger.valueOf(123));
Document document = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument();
Marshaller marshaller = JAXBContext.newInstance(Farm.class).createMarshaller();
marshaller.marshal(farm, document);
SOAPMessage soapMessage = MessageFactory.newInstance().createMessage();
soapMessage.getSOAPBody().addDocument(document);
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
soapMessage.writeTo(outputStream);
String output = new String(outputStream.toByteArray());
Демаршаллизация
String example =
"<soapenv:Envelope xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\"><soapenv:Header /><soapenv:Body><ns2:farm xmlns:ns2=\"http://adamish.com/example/farm\"><horse height=\"123\" name=\"glue factory\"/></ns2:farm></soapenv:Body></soapenv:Envelope>";
SOAPMessage message = MessageFactory.newInstance().createMessage(null,
new ByteArrayInputStream(example.getBytes()));
Unmarshaller unmarshaller = JAXBContext.newInstance(Farm.class).createUnmarshaller();
Farm farm = (Farm)unmarshaller.unmarshal(message.getSOAPBody().extractContentAsDocument());
Ответ 2
Вот как вы можете обрабатывать свое использование cae:
Если вам нужно отобразить элемент Envelope
пакет-инфо
Обычно вы используете @XmlSchema
следующим образом. Использование свойств namespace
и elementFormDefault
, как я сделал, означает, что все данные, сопоставленные с элементами XML, если иначе отображаемое не будет принадлежать пространству имен http://www.xxxx.com/ncp/oomr/dto/
. Информация, указанная в xmlns
, предназначена для генерации XML-схемы, хотя некоторые реализации JAXB используют это, чтобы определить предпочтительный префикс для пространства имен при сортировке (см. http://blog.bdoughan.com/2011/11/jaxb-and-namespace-prefixes.html).
@XmlSchema (
namespace="http://www.xxxx.com/ncp/oomr/dto/",
elementFormDefault=XmlNsForm.QUALIFIED,
xmlns = {
@XmlNs(prefix = "env", namespaceURI="http://schemas.xmlsoap.org/soap/envelope/"),
@XmlNs(prefix="whatever", namespaceURI="http://www.xxxx.com/ncp/oomr/dto/")
}
)
package com.one.two;
import javax.xml.bind.annotation.*;
Конверт
Если в com.one.two
вам нужно сопоставить элементы из пространства имен, отличного от http://www.xxxx.com/ncp/oomr/dto/
, то вам нужно указать его в аннотациях @XmlRootElement
и @XmlElement
.
package com.one.two;
import javax.xml.bind.annotation.*;
@XmlRootElement(name="Envelope", namespace="http://schemas.xmlsoap.org/soap/envelope/")
@XmlAccessorType(XmlAccessType.FIELD)
public class Envelope {
@XmlElement(name="Body", namespace="http://schemas.xmlsoap.org/soap/envelope/")
private Body body;
}
Дополнительная информация
Если вы просто хотите отобразить тело
Вы можете использовать синтаксический анализатор StAX для синтаксического анализа сообщения и перехода к части полезной нагрузки и отменить его:
import javax.xml.bind.*;
import javax.xml.stream.*;
import javax.xml.transform.stream.StreamSource;
public class UnmarshalDemo {
public static void main(String[] args) throws Exception {
XMLInputFactory xif = XMLInputFactory.newFactory();
StreamSource xml = new StreamSource("src/blog/stax/middle/input.xml");
XMLStreamReader xsr = xif.createXMLStreamReader(xml);
xsr.nextTag();
while(!xsr.getLocalName().equals("return")) {
xsr.nextTag();
}
JAXBContext jc = JAXBContext.newInstance(Customer.class);
Unmarshaller unmarshaller = jc.createUnmarshaller();
JAXBElement<Customer> jb = unmarshaller.unmarshal(xsr, Customer.class);
xsr.close();
}
}
Дополнительная информация
Ответ 3
Просто хотел добавить к существующим ответам - в то время как unmarshalling, если XML-документ не является пространством имен, вы можете получить сообщение об ошибке: javax.xml.bind.UnmarshalException: неожиданный элемент (uri: " http://some.url"; local: "someOperation" )
Если это так, вы можете просто использовать другой метод для unmarshaller:
Unmarshaller unmarshaller = JAXBContext.newInstance(YourObject.class).createUnmarshaller();
JAXBElement<YourObject> element = unmarshaller.unmarshal(message.getSOAPBody().extractContentAsDocument(), YourObject.class);
YourObject yo = element.getValue();