2011-11-20 54 views
4
我使用JAXB使用Scala

屬性,我的編組的代碼如下所示:如何設置非名稱空間的零和數據類型在JAXB

def marshalToXml(): String = { 
    val context = JAXBContext.newInstance(this.getClass()) 
    val writer = new StringWriter 
    context.createMarshaller.marshal(this, writer) 
    writer.toString() 
} 

然後我爲空的元素,我使用註釋@XmlElement(nillable = true)爲每JAXB Marshalling with null fields。這給了我的XML輸出像這樣:

<name>Alex Dean</name> 
<customerReference xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:nil="true"/> 
<quantity>1</quantity> 
<createdAt>2011-05-14T00:00:00+03:00</createdAt> 

這是一個良好的開端,但我真的很想元帥這些領域是:

<name>Alex Dean</name> 
<customerReference nil="true"/> 
<quantity type="integer">1</quantity> 
<createdAt type="datetime">2011-05-14T00:00:00+03:00</createdAt> 

換句話說,我想刪除命名空間屬性和前綴,併爲除字符串外的所有字符添加明確的XML數據類型屬性。這可能很簡單,但我似乎無法在JAXB文檔中找到。

任何幫助感激地收到!

回答

5

你可以使用JAXB用的StAX解析器和執行以下操作:

客戶

在你的領域模型的每個屬性將與@XmlElement(nillable=true, type=Object.class)映射。設置type=Object.class將強制寫出xsi:type屬性。

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

我們將編寫一個XMLStreamWriter是剝去所有我們不希望寫入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

我們需要創建一個XMLStreamReader包裝,增加了我們對XMLStreamWriter剝去了一切。由於我們可以擴展StreamReaderDelegate,所以對於XMLStreamReader更容易。

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


} 

演示

下面演示瞭如何一切走到一起:

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

} 

輸出

<?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 
+1

非常感謝布萊斯 - 這個偉大工程。只需注意Scala用戶 - 類型註解的Scala等價語法是:@XmlElement(\'type \'= classOf [Object])''。另外我想問一下'XMLStreamReaderWrapper'--因爲我看不到這是如何連接到你的__Demo__中的解組? –

相關問題