How to set non-namespaced nil and datatype attributes in JAXB

前端 未结 1 1369
情话喂你
情话喂你 2020-12-30 17:18

I\'m using JAXB with Scala, my marshalling code looks like this:

def marshalToXml(): String = {
  val context = JAXBContext.newInstance(this.getClass())
  va         


        
相关标签:
1条回答
  • 2020-12-30 18:09

    You could use JAXB with a StAX parser and do the following:

    Customer

    Each property in your domain model will be mapped with @XmlElement(nillable=true, type=Object.class). Setting the type=Object.class will force an xsi:type attribute to be written out.

    package forum8198945;
    
    import java.util.Date;  
    import javax.xml.bind.annotation.*;
    
    @XmlRootElement
    public class Customer {
    
        private String name;
        private Customer customerReference;
        private Integer quantity;
        private Date createdAt;
    
        @XmlElement(nillable=true, type=Object.class)
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        @XmlElement(nillable=true, type=Object.class)
        public Customer getCustomerReference() {
            return customerReference;
        }
    
        public void setCustomerReference(Customer customerReference) {
            this.customerReference = customerReference;
        }
    
        @XmlElement(nillable=true, type=Object.class)
        public Integer getQuantity() {
            return quantity;
        }
    
        public void setQuantity(Integer quantity) {
            this.quantity = quantity;
        }
    
        @XmlElement(nillable=true, type=Object.class)
        public Date getCreatedAt() {
            return createdAt;
        }
    
        public void setCreatedAt(Date createdAt) {
            this.createdAt = createdAt;
        }
    
    }
    

    XMLStreamWriterWrapper

    We will write a create a wrapper for an XMLStreamWriter that strips off all the information we do not want written to XML.

    package forum8198945;
    
    import javax.xml.namespace.NamespaceContext;
    import javax.xml.stream.XMLStreamException;
    import javax.xml.stream.XMLStreamWriter;
    
    public class XMLStreamWriterWrapper implements XMLStreamWriter {
    
        private XMLStreamWriter xmlStreamWriter;
    
        public XMLStreamWriterWrapper(XMLStreamWriter xmlStreamWriter) {
            this.xmlStreamWriter = xmlStreamWriter;
        }
    
        public void writeStartElement(String localName) throws XMLStreamException {
            xmlStreamWriter.writeStartElement(localName);
        }
    
        public void writeStartElement(String namespaceURI, String localName) throws XMLStreamException {
            xmlStreamWriter.writeStartElement(namespaceURI, localName);
        }
    
        public void writeStartElement(String prefix, String localName, String namespaceURI) throws XMLStreamException {
            xmlStreamWriter.writeStartElement(prefix, localName, namespaceURI);
        }
    
        public void writeEmptyElement(String namespaceURI, String localName) throws XMLStreamException {
            xmlStreamWriter.writeEmptyElement(namespaceURI, localName);
        }
    
        public void writeEmptyElement(String prefix, String localName, String namespaceURI) throws XMLStreamException {
            xmlStreamWriter.writeEmptyElement(prefix, localName, namespaceURI);
        }
    
        public void writeEmptyElement(String localName) throws XMLStreamException {
            xmlStreamWriter.writeEmptyElement(localName);
        }
    
        public void writeEndElement() throws XMLStreamException {
            xmlStreamWriter.writeEndElement();
        }
    
        public void writeEndDocument() throws XMLStreamException {
            xmlStreamWriter.writeEndDocument();
        }
    
        public void close() throws XMLStreamException {
            xmlStreamWriter.close();
        }
    
        public void flush() throws XMLStreamException {
            xmlStreamWriter.flush();
        }
    
        public void writeAttribute(String localName, String value) throws XMLStreamException {
            xmlStreamWriter.writeAttribute(localName, value);
        }
    
        public void writeAttribute(String prefix, String namespaceURI, String localName, String value) throws XMLStreamException {
            if("http://www.w3.org/2001/XMLSchema-instance".equals(namespaceURI)) {
                int colonIndex = value.indexOf(':');
                if(colonIndex > -1) {
                    value = value.substring(colonIndex + 1);
                }
                xmlStreamWriter.writeAttribute(localName, value);
            } else {
                xmlStreamWriter.writeAttribute(prefix, namespaceURI, localName, value);
            }
        }
    
        public void writeAttribute(String namespaceURI, String localName, String value) throws XMLStreamException {
            if("http://www.w3.org/2001/XMLSchema-instance".equals(namespaceURI)) {
                int colonIndex = value.indexOf(':');
                if(colonIndex > -1) {
                    value = value.substring(colonIndex + 1);
                }
                xmlStreamWriter.writeAttribute(localName, value);
            } else {
                xmlStreamWriter.writeAttribute(namespaceURI, localName, value);
            }
        }
    
        public void writeNamespace(String prefix, String namespaceURI) throws XMLStreamException {
            if(!"http://www.w3.org/2001/XMLSchema-instance".equals(namespaceURI) && !"http://www.w3.org/2001/XMLSchema".equals(namespaceURI)) {
                xmlStreamWriter.writeNamespace(prefix, namespaceURI);
            }
        }
    
        public void writeDefaultNamespace(String namespaceURI) throws XMLStreamException {
            if(!"http://www.w3.org/2001/XMLSchema-instance".equals(namespaceURI)) {
                xmlStreamWriter.writeDefaultNamespace(namespaceURI);
            }
        }
    
        public void writeComment(String data) throws XMLStreamException {
            // TODO Auto-generated method stub
        }
    
        public void writeProcessingInstruction(String target) throws XMLStreamException {
            // TODO Auto-generated method stub
        }
    
        public void writeProcessingInstruction(String target, String data) throws XMLStreamException {
            // TODO Auto-generated method stub
        }
    
        public void writeCData(String data) throws XMLStreamException {
            // TODO Auto-generated method stub
        }
    
        public void writeDTD(String dtd) throws XMLStreamException {
            // TODO Auto-generated method stub
        }
    
        public void writeEntityRef(String name) throws XMLStreamException {
            // TODO Auto-generated method stub
        }
    
        public void writeStartDocument() throws XMLStreamException {
            xmlStreamWriter.writeStartDocument();
        }
    
        public void writeStartDocument(String version) throws XMLStreamException {
            xmlStreamWriter.writeStartDocument(version);
        }
    
        public void writeStartDocument(String encoding, String version) throws XMLStreamException {
            xmlStreamWriter.writeStartDocument(encoding, version);
        }
    
        public void writeCharacters(String text) throws XMLStreamException {
            xmlStreamWriter.writeCharacters(text);
        }
    
        public void writeCharacters(char[] text, int start, int len) throws XMLStreamException {
            xmlStreamWriter.writeCharacters(text, start, len);
        }
    
        public String getPrefix(String uri) throws XMLStreamException {
            return xmlStreamWriter.getPrefix(uri);
        }
    
        public void setPrefix(String prefix, String uri) throws XMLStreamException {
            xmlStreamWriter.setPrefix(prefix, uri);
        }
    
        public void setDefaultNamespace(String uri) throws XMLStreamException {
            xmlStreamWriter.setDefaultNamespace(uri);
        }
    
        public void setNamespaceContext(NamespaceContext context) throws XMLStreamException {
            xmlStreamWriter.setNamespaceContext(context);
        }
    
        public NamespaceContext getNamespaceContext() {
            return xmlStreamWriter.getNamespaceContext();
        }
    
        public Object getProperty(String name) throws IllegalArgumentException {
            return xmlStreamWriter.getProperty(name);
        }
    
    }
    

    XMLStreamReaderWrapper

    We need to create a wrapper for XMLStreamReader that adds everything that we stripped off on the XMLStreamWriter. This is easier to do for XMLStreamReader since we can extend StreamReaderDelegate.

    package forum8198945;
    
    import javax.xml.stream.XMLStreamReader;
    import javax.xml.stream.util.StreamReaderDelegate;
    
    public class XMLStreamReaderWrapper extends StreamReaderDelegate {
    
        public XMLStreamReaderWrapper(XMLStreamReader xmlStreamReader) {
            super(xmlStreamReader);
        }
    
        @Override
        public String getAttributeNamespace(int index) {
            String attributeName = getAttributeLocalName(index);
            if("type".equals(attributeName) || "nil".equals(attributeName)) {
                return "http://www.w3.org/2001/XMLSchema-instance";
            }
            return super.getAttributeNamespace(index);
        }
    
    
    }
    

    Demo

    The following demonstrates how everything comes together:

    package forum8198945;
    
    import java.io.StringReader;
    import java.io.StringWriter;
    import java.util.Date;
    
    import javax.xml.bind.JAXBContext;
    import javax.xml.bind.Marshaller;
    import javax.xml.stream.XMLInputFactory;
    import javax.xml.stream.XMLOutputFactory;
    import javax.xml.stream.XMLStreamWriter;
    
    public class Demo {
    
        public static void main(String[] args) throws Exception {
            JAXBContext jc = JAXBContext.newInstance(Customer.class);
    
            Customer customer = new Customer();
            customer.setName("Alex Dean");
            customer.setCustomerReference(null);
            customer.setQuantity(1);
            customer.setCreatedAt(new Date());
    
            StringWriter stringWriter = new StringWriter();
            XMLOutputFactory xof = XMLOutputFactory.newFactory();
            XMLStreamWriter xsw = xof.createXMLStreamWriter(stringWriter);
            xsw = new XMLStreamWriterWrapper(xsw);
            Marshaller marshaller = jc.createMarshaller();
            marshaller.marshal(customer, xsw);
    
            String xml = stringWriter.toString();
            System.out.println(xml);
    
            XMLInputFactory xif = XMLInputFactory.newFactory();
            xif.createXMLStreamReader(new StringReader(xml));
    
            printValue(customer.getName());
            printValue(customer.getCustomerReference());
            printValue(customer.getQuantity());
            printValue(customer.getCreatedAt());
        }
    
        private static void printValue(Object value) {
            System.out.print(value);
            System.out.print(" ");
            if(null != value) {
                System.out.print(value.getClass());
            }
            System.out.println();
        }
    
    }
    

    Output

    <?xml version="1.0"?><customer><createdAt type="dateTime">2011-11-25T13:36:49.095</createdAt><customerReference nil="true"></customerReference><name type="string">Alex Dean</name><quantity type="int">1</quantity></customer>
    Alex Dean class java.lang.String
    null 
    1 class java.lang.Integer
    Fri Nov 25 13:36:49 EST 2011 class java.util.Date
    
    0 讨论(0)
提交回复
热议问题