J'utilise JAXB pour analyser les éléments XML de la réponse SOAP. J'ai défini les classes POJO pour les éléments XML. J'ai testé des classes pojo sans espace de noms et préfixes son fonctionnement correct. Bien quand j'essaye d'analyser avec les espaces de noms et le préfixe faisant face à l'exception suivante.Requirement consiste à analyser l'entrée de SOAPMessage Object
javax.xml.bind.UnmarshalException: unexpected element (uri:"http://schemas.xmlsoap.org/soap/envelope/", local:"Envelope"). Expected elements are <{}Envelope>
J'ai essayé de résoudre le problème en créant @XMLSchema pour le paquet dans package-info.Java et en localisant ce fichier dans le dossier package.Can est-il possible que l'un d'entre eux me guide pour aller de l'avant?
Référencé cet article, mais ne m'a pas aidé.
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;
Merci d'avance
Cela peut être fait sans modifier le code JAXB généré à l'aide de la classe SOAPMessage standard. J'ai écrit à ce sujet ici et ici
C'est un peu délicat mais fonctionne correctement.
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());
Voici comment vous pouvez gérer votre utilisation cae:
Envelope
package-info
En règle générale, vous utiliseriez le @XmlSchema
comme suit. Utiliser les propriétés namespace
et elementFormDefault
comme je l’ai déjà fait signifie que toutes les données mappées sur des éléments XML, sauf si mappé autrement, appartiennent à l’espace de nom http://www.xxxx.com/ncp/oomr/dto/
. Les informations spécifiées dans xmlns
concernent la génération de schémas XML, bien que certaines implémentations de JAXB l'utilisent pour déterminer le préfixe préféré d'un espace de noms lors du marshalling (voir: 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.*;
Enveloppe
Si vous devez mapper des éléments d'un espace-noms autre que com.one.two
dans http://www.xxxx.com/ncp/oomr/dto/
, vous devez le spécifier dans les annotations @XmlRootElement
et @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;
}
Pour plus d'informations
Vous pouvez utiliser un analyseur syntaxique StAX pour analyser le message, puis passer à la portion de charge utile et effectuer la récupération à partir de là:
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();
}
}
Pour plus d'informations
Je voulais juste ajouter des éléments aux réponses existantes - tout en précisant si le document XML n'est pas sensible à l'espace de noms, vous risquez de recevoir une erreur: javax.xml.bind.UnmarshalException: élément inattendu (uri: " http: //some.url ";, local:" someOperation ")
Si tel est le cas, vous pouvez simplement utiliser une méthode différente sur l’unmarshaller:
Unmarshaller unmarshaller = JAXBContext.newInstance(YourObject.class).createUnmarshaller();
JAXBElement<YourObject> element = unmarshaller.unmarshal(message.getSOAPBody().extractContentAsDocument(), YourObject.class);
YourObject yo = element.getValue();