JAXB unmarshall with namespaces and prefix

后端 未结 3 1881
暗喜
暗喜 2020-11-30 04:34

I am using JAXB to parse xml elements from the SOAP response. I have defined POJO classes for the xml elements. I have tested pojo classes without namespace and prefix its w

相关标签:
3条回答
  • 2020-11-30 04:39

    Here is how you can handle your use cae:

    If You Need to Map the Envelope Element

    package-info

    Typically you would use the @XmlSchema as follows. Using the namespace and elementFormDefault properties like I've done means that all data mapped to XML elements unless otherwise mapped will belong to the http://www.xxxx.com/ncp/oomr/dto/ namespace. The information specified in xmlns is for XML schema generation altough some JAXB implementations use this to determine the preferred prefix for a namespace when marshalling (see: 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.*;
    

    Envelope

    If within the com.one.two you need to map to elements from a namespace other than http://www.xxxx.com/ncp/oomr/dto/ then you need to specify it in the @XmlRootElement and @XmlElement annotations.

    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;
    
    }
    

    For More Information

    • http://blog.bdoughan.com/2010/08/jaxb-namespaces.html

    If You Just Want to Map the Body

    You can use a StAX parser to parse the message and advance to the payload portion and unmarshal from there:

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

    For More Information

    • http://blog.bdoughan.com/2012/08/handle-middle-of-xml-document-with-jaxb.html
    0 讨论(0)
  • 2020-11-30 05:02

    Just wanted to add onto the existing answers -- while unmarshalling if the XML document is not namespace aware you might receive an error: javax.xml.bind.UnmarshalException: unexpected element (uri:"http://some.url";, local:"someOperation")

    If this is the case you can simply use a different method on the unmarshaller:

    Unmarshaller unmarshaller = JAXBContext.newInstance(YourObject.class).createUnmarshaller();
    JAXBElement<YourObject> element = unmarshaller.unmarshal(message.getSOAPBody().extractContentAsDocument(), YourObject.class);
    YourObject yo = element.getValue();
    
    0 讨论(0)
  • 2020-11-30 05:03

    This can be done without modifying the generated JAXB code using standard SOAPMessage class. I wrote about this here and here

    It's a little fiddly but works correctly.

    Marshalling

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

    Unmarshalling

    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());
    
    0 讨论(0)
提交回复
热议问题