JAXB: How can I unmarshal XML without namespaces JAXB: How can I unmarshal XML without namespaces xml xml

JAXB: How can I unmarshal XML without namespaces


An easier way might be to use unmarshalByDeclaredType, since you already know the type you want to unmarshal.

By using

Unmarshaller.unmarshal(rootNode, MyType.class);

you don't need to have a namespace declaration in the XML, since you pass in the JAXBElement that has the namespace already set.

This also perfectly legal, since you are not required to reference a namespace in an XML instance, see http://www.w3.org/TR/xmlschema-0/#PO - and many clients produce XML in that fashion.

Finally got it to work. Note that you have to remove any custom namespace in the schema; here's working sample code:

The schema:

<xsd:schema   xmlns:xsd="http://www.w3.org/2001/XMLSchema"><xsd:element name="customer">   <xsd:complexType>      <xsd:sequence minOccurs="1" maxOccurs="1">         <xsd:element name="name" type="xsd:string" minOccurs="1" maxOccurs="1" />         <xsd:element name="phone" type="xsd:string" minOccurs="1" maxOccurs="1" />      </xsd:sequence>   </xsd:complexType></xsd:element>

XML:

<?xml version="1.0" encoding="UTF-8"?><customer>   <name>Jane Doe</name>   <phone>08154712</phone></customer>

JAXB code:

JAXBContext jc = JAXBContext.newInstance(Customer.class);Unmarshaller u = jc.createUnmarshaller();u.setSchema(schemaInputStream); // load your schema from File or any streamsourceCustomer = u.unmarshal(new StreamSource(inputStream), clazz);  // pass in your XML as inputStream


UPDATE

You can get this to work by introducing an intermediate layer to translate between type and xsi:type. Below is example of using the StAX StreamReaderDelegate to do this for the JAXB unmarshal operation:

package forum7184526;import java.io.FileInputStream;import javax.xml.bind.JAXBContext;import javax.xml.bind.Unmarshaller;import javax.xml.stream.XMLInputFactory;import javax.xml.stream.XMLStreamReader;import javax.xml.stream.util.StreamReaderDelegate;import org.eclipse.persistence.oxm.XMLConstants;public class Demo {    public static void main(String[] args) throws Exception {        XMLInputFactory xif = XMLInputFactory.newFactory();        XMLStreamReader xsr = xif.createXMLStreamReader(new FileInputStream("input.xml"));        xsr = new XsiTypeReader(xsr);        JAXBContext jc = JAXBContext.newInstance(Spec.class);        Unmarshaller unmarshaller = jc.createUnmarshaller();        Spec spec = (Spec) unmarshaller.unmarshal(xsr);    }    private static class XsiTypeReader extends StreamReaderDelegate {        public XsiTypeReader(XMLStreamReader reader) {            super(reader);        }        @Override        public String getAttributeNamespace(int arg0) {            if("type".equals(getAttributeLocalName(arg0))) {                return XMLConstants.SCHEMA_INSTANCE_URL;            }            return super.getAttributeNamespace(arg0);        }    }}

xsi:type is a schema mechanism for specifying the real type of an element (similar to a cast in Java). If you remove the namespace, you are changing the semantics of the document.

In EclipseLink JAXB (MOXy) we allow you to specify your own inheritance indicator for domain objects using @XmlDescriminatorNode and @XmlDescrimatorValue. We currently do not offer this type of customization for data type properties:


Based on Blaise's comments (thanks Blaise!) and my research.Here is the solution to my problem. Do you agree with that Blaise, or you have a better way?

package forum7184526;import java.io.FileInputStream;import javax.xml.bind.JAXBContext;import javax.xml.bind.Unmarshaller;import javax.xml.stream.XMLInputFactory;import javax.xml.stream.XMLStreamReader;import javax.xml.stream.util.StreamReaderDelegate;import org.eclipse.persistence.oxm.XMLConstants;public class Demo {public static void main(String[] args) throws Exception {    XMLInputFactory xif = XMLInputFactory.newFactory();    XMLStreamReader xsr = xif.createXMLStreamReader(new FileInputStream("input.xml"));    xsr = new XsiTypeReader(xsr);    JAXBContext jc = JAXBContext.newInstance(Spec.class);    Unmarshaller unmarshaller = jc.createUnmarshaller();    Spec spec = (Spec) unmarshaller.unmarshal(xsr);}private static class XsiTypeReader extends StreamReaderDelegate {    public XsiTypeReader(XMLStreamReader reader) {        super(reader);    }    @Override    public String getAttributeNamespace(int arg0) {        if("type".equals(getAttributeLocalName(arg0))) {            return "http://www.w3.org/2001/XMLSchema-instance";        }        return super.getAttributeNamespace(arg0);    }    @Override    public String getAttributeValue(int arg0) {      String n = getAttributeLocalName(arg0);      if("type".equals(n)) {         String v = super.getAttributeValue(arg0);          return  "xs:"+ v;      }      return super.getAttributeValue(arg0);    }    @Override    public NamespaceContext getNamespaceContext() {      return new MyNamespaceContext(super.getNamespaceContext());    }}private static class MyNamespaceContext implements NamespaceContext {  public NamespaceContext _context;  public MyNamespaceContext(NamespaceContext c){     _context = c;  }  @Override  public Iterator<?> getPrefixes(String namespaceURI) {     return _context.getPrefixes(namespaceURI);  }  @Override  public String getPrefix(String namespaceURI) {     return _context.getPrefix(namespaceURI);  }  @Override  public String getNamespaceURI(String prefix) {     if("xs".equals(prefix)) {        return  "http://www.w3.org/2001/XMLSchema";     }     return _context.getNamespaceURI(prefix);  }}}