问题描述
您可以将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;
}
}
我们将为创建一个包装器,以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);
}
}
我们需要为此创建一个包装器,XMLStreamReader
以添加我们在上剥离的所有内容XMLStreamWriter
。XMLStreamReader
因为我们可以扩展,所以这样做更容易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);
}
}
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
解决方法
我在Scala中使用JAXB,编组代码如下所示:
def marshalToXml(): String = {
val context = JAXBContext.newInstance(this.getClass())
val writer = new StringWriter
context.createMarshaller.marshal(this,writer)
writer.toString()
}
然后对于我的可为null的元素,我将@XmlElement(nillable =
true)
按照JAXB编组使用带有null字段的注释。这使我的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文档中找到方法。
任何帮助表示感谢!