如果已经回答,我很抱歉,但我一直在使用的搜索词(即 JAXB @XmlAttribute压缩 或 JAXB XML marshal to字符串不同的结果 )没有提出任何结果。
我正在使用JAXB取消/编组使用@XmlElement
和@XmlAttribute
注释注释的对象。我有一个格式化程序类,它提供了两个方法 - 一个包装marshal方法并接受对象编组和OutputStream
,另一个只接受对象并将XML输出作为String返回。不幸的是,这些方法不能为相同的对象提供相同的输出。封送到文件时,内部标有@XmlAttribute
的简单对象字段将打印为:
<element value="VALUE"></element>
当编组到一个字符串时,它们是:
<element value="VALUE"/>
我更喜欢这两种情况的第二种格式,但我很好奇如何控制差异,并且无论如何都会满足于它们。我甚至创建了一个静态编组器,两种方法都使用它来消除不同的实例值。格式代码如下:
/** Marker interface for classes which are listed in jaxb.index */
public interface Marshalable {}
/** Local exception class */
public class XMLMarshalException extends BaseException {}
/** Class which un/marshals objects to XML */
public class XmlFormatter {
private static Marshaller marshaller = null;
private static Unmarshaller unmarshaller = null;
static {
try {
JAXBContext context = JAXBContext.newInstance("path.to.package");
marshaller = context.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
marshaller.setProperty(Marshaller.JAXB_ENCODING, "UTF-8");
unmarshaller = context.createUnmarshaller();
} catch (JAXBException e) {
throw new RuntimeException("There was a problem creating a JAXBContext object for formatting the object to XML.");
}
}
public void marshal(Marshalable obj, OutputStream os) throws XMLMarshalException {
try {
marshaller.marshal(obj, os);
} catch (JAXBException jaxbe) {
throw new XMLMarshalException(jaxbe);
}
}
public String marshalToString(Marshalable obj) throws XMLMarshalException {
try {
StringWriter sw = new StringWriter();
return marshaller.marshal(obj, sw);
} catch (JAXBException jaxbe) {
throw new XMLMarshalException(jaxbe);
}
}
}
/** Example data */
@XmlType
@XmlAccessorType(XmlAccessType.FIELD)
public class Data {
@XmlAttribute(name = value)
private String internalString;
}
/** Example POJO */
@XmlType
@XmlRootElement(namespace = "project/schema")
@XmlAccessorType(XmlAccessType.FIELD)
public class Container implements Marshalable {
@XmlElement(required = false, nillable = true)
private int number;
@XmlElement(required = false, nillable = true)
private String word;
@XmlElement(required = false, nillable = true)
private Data data;
}
调用marshal(container, new FileOutputStream("output.xml"))
和marshalToString(container)
的结果如下:
输出到文件
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<ns2:container xmlns:ns2="project/schema">
<number>1</number>
<word>stackoverflow</word>
<data value="This is internal"></data>
</ns2:container>
和
输出到字符串
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<ns2:container xmlns:ns2="project/schema">
<number>1</number>
<word>stackoverflow</word>
<data value="This is internal"/>
</ns2:container>
答案 0 :(得分:8)
看起来这可能是JAXB中的“错误”。查看源代码,调用marshal()会根据输出/编写器类型参数创建不同的编写器:
public void marshal(Object obj, OutputStream out, NamespaceContext inscopeNamespace) throws JAXBException {
write(obj, createWriter(out), new StAXPostInitAction(inscopeNamespace,serializer));
}
public void marshal(Object obj, XMLStreamWriter writer) throws JAXBException {
write(obj, XMLStreamWriterOutput.create(writer,context), new StAXPostInitAction(writer,serializer));
}
编写器的实现在处理“空元素”方面有所不同。以上代码来自:
JAXB里\运行时\ SRC \ COM \太阳\ XML \绑定\ V2 \运行时\ MarshallerImpl.java。
您正在创作的两位作家是:
JAXB里\运行时\ SRC \ COM \太阳\ XML \绑定\ V2 \运行时\输出\ UTF8XmlOutput.java
JAXB里\运行时\ SRC \ COM \太阳\ XML \绑定\ V2 \运行时\输出\ XMLStreamWriterOutput.java
答案 1 :(得分:2)
好消息是JAXB是一个具有多个实现的规范(就像JPA一样)。如果一个实现不能满足您的需求,则可以使用其他实现,例如EclipseLink JAXB(MOXy):
答案 2 :(得分:1)
我不知道为什么JAXB会这样做 - 或者即使它是JAXB - 例如,如果JAXB通过SAXContentHandler输出XML,那么它无法直接控制标签的生成方式。
要获得一致的行为,可以将OutputStream包装在OutputStreamWriter中,例如
public void marshal(Marshalable obj, OutputStream os) throws XMLMarshalException {
try {
marshaller.marshal(obj, new OutputStreamWriter(os, "UTF-8"));
} catch (JAXBException jaxbe) {
throw new XMLMarshalException(jaxbe);
}
}
同样,如果将StringWriter包装在PrintWriter中,您可能会看到会发生什么。也许有一些自定义代码会检测StringWriter
以尝试尽可能缩短输出。听起来不太可能,但我没有其他解释。
答案 3 :(得分:0)
为什么重要? &lt; tag attribute =“value”&gt;&lt; / tag&gt;相当于&lt; tag attribute =“value”/&gt;在xml中