web-dev-qa-db-fra.com

JAXB unmarshal avec espace de noms et préfixe

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

13
gks

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.

Triage

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());

Unarsing

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());
16
Adam

Voici comment vous pouvez gérer votre utilisation cae:

Si vous devez mapper l'élément 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

Si vous voulez juste cartographier le corps

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

13
Blaise Doughan

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();
1
ptdunlap