web-dev-qa-db-fra.com

Comment dé-marshall SOAP en utilisant JAXB si la déclaration d'espace de noms est activée SOAP?

JAXB ne peut supprimer un XML que si l'enveloppe de savon a déjà été supprimée. Cependant, la réponse SOAP que j'essaye de démarshall a sa déclaration d'espace de noms sur l'enveloppe de savon. Si je supprime l'enveloppe de savon, la déclaration d'espace de noms sera également supprimée. En tant que tel, le préfixe de la les balises ne feront référence à aucune. Cela provoque une erreur de JAXB. Comment puis-je annuler la réponse SOAP à l'aide de JAXB si l'espace de noms est déclaré sur le SOAP enveloppe?

Un échantillon similaire du XML dont j'ai besoin pour démarshall est ci-dessous:

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns="http://example.com/">
    <soapenv:Body>
        <ns:getNumberResponse>
            <number>123456789</number>
        </ns:getNumberResponse>
    </soapenv:Body>
</soapenv:Envelope>

Voici ce qui se passe si je retire l'enveloppe de savon:

<ns:getNumberResponse>
    <number>123456789</number>
</ns:getNumberResponse>

Si j'ai retiré l'enveloppe de savon, la déclaration d'espace de noms aura également disparu. JAXB ne pourra pas dé-marshaller le xml ci-dessus car la définition de l'espace de noms pour le préfixe "ns" est manquante. En tant que tel, il renverra un "The prefix "ns" for element "ns:getNumberResponse" is not bound." Message d'erreur. Comment je le répare?

Veuillez noter que j'utilise JDK 1.5. Je ne sais pas s'il existe un moyen de résoudre ce problème dans JDK 1.6. J'ai pu utiliser JAXB car j'ai téléchargé les fichiers JAR requis pour utiliser JAXB.

19
Arci

Vous pouvez utiliser un analyseur StAX pour analyser le message SOAP, puis faire avancer XMLStreamReader vers l'élément getNumberResponse et utiliser la méthode unmarshal qui prend un paramètre de classe. Un analyseur StAX est inclus dans Java SE 6, mais vous devrez en télécharger un pour Java SE 5. Woodstox est un analyseur StAX populaire.

Réponse

package forum11465653;

public class Response {

    private long number;

    public long getNumber() {
        return number;
    }

    public void setNumber(long number) {
        this.number = number;
    }

}

Démo

Un XMLStreamReader a un NamespaceContext. Le NamespaceContext connaît toutes les déclarations d'espace de noms actives pour le niveau actuel. Votre implémentation JAXB (JSR-222) pourra en tirer parti pour obtenir les informations nécessaires.

package forum11465653;

import Java.io.FileReader;
import javax.xml.bind.*;
import javax.xml.stream.*;

public class Demo {

    public static void main(String[] args) throws Exception{
        XMLInputFactory xif = XMLInputFactory.newFactory();
        XMLStreamReader xsr = xif.createXMLStreamReader(new FileReader("src/forum11465653/input.xml"));
        xsr.nextTag(); // Advance to Envelope tag
        xsr.nextTag(); // Advance to Body tag
        xsr.nextTag(); // Advance to getNumberResponse tag
        System.out.println(xsr.getNamespaceContext().getNamespaceURI("ns"));

        JAXBContext jc = JAXBContext.newInstance(Response.class);
        Unmarshaller unmarshaller = jc.createUnmarshaller();
        JAXBElement<Response> je = unmarshaller.unmarshal(xsr, Response.class);
        System.out.println(je.getName());
        System.out.println(je.getValue());
    }

}

Sortie

http://example.com/
{http://example.com/}getNumberResponse
forum11465653.Response@781f6226
36
bdoughan

Vous pouvez analyser l'ensemble du message SOAP à l'aide d'un analyseur DOM, qui serait en mesure de résoudre tous les espaces de noms au moment de l'analyse. Ensuite, extrayez l'élément dont vous avez besoin de l'arborescence DOM résultante et transmettez-le au unmarshaller.

DomDemo

package forum11465653;

import Java.io.File;
import javax.xml.bind.*;
import javax.xml.parsers.*;
import javax.xml.transform.dom.DOMSource;
import org.w3c.dom.*;

public class DomDemo {

    public static void main(String[] args) throws Exception{
        DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
        dbf.setNamespaceAware(true);
        DocumentBuilder db = dbf.newDocumentBuilder();
        Document d = db.parse(new File("src/forum11465653/input.xml"));
        Node getNumberResponseElt = d.getElementsByTagNameNS("http://example.com/", "getNumberResponse").item(0);

        JAXBContext jc = JAXBContext.newInstance(Response.class);
        Unmarshaller unmarshaller = jc.createUnmarshaller();
        JAXBElement<Response> je = unmarshaller.unmarshal(new DOMSource(getNumberResponseElt), Response.class);
        System.out.println(je.getName());
        System.out.println(je.getValue());
    }

}

Sortie

{http://example.com/}getNumberResponse
forum11465653.Response@19632847
17
Ian Roberts