[英]Write empty tag with JAXB and XMLStreamWriter
我正在使用标准的JAXB实现。
这是我的带注释的类(是一组类的一部分)
@XmlType()
@XmlAccessorType(FIELD)
class MyClass {
@XmlValue
protected final String value = null;
@XmlAttribute
protected String attr;
...get/set for attr...
}
我正在编写root对象
JaxbContext ctx = JAXBContext.newInstance("path.to.package");
XMLStreamWriter writer = new IndentingXMLStreamWriter(file); //stax-utils writer
ctx.marshal(rootObject, writer);
结果是<my-class attr="attrValue"></my-class>
但我需要空标记为<my-class attr="attrValue"/>
。 我尝试了编写器和目标流的一些不同组合(并读取了十几个SO问题)(不仅是文件,还有StringWriter和其他人,但我需要将对象保存到文件中)。 任何建议或解决方案?
这是编组到XMLStreamWriter
时可能出现的问题。 如果您可以编组到File
, FileOutputStream
或FileWriter
以获取您正在寻找的行为。
注意:
要使用这些输出目标格式化输出,可以在Marshaller
上设置以下属性:
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
我解决了使用自定义XMLStreamWriter,如果tag-name根本没有内容,则将<tag-name></tag-name>
替换为<tag-name/>
。 背后的想法是推迟startElement-endElement之间的写事件。 当找到endElement时 ,如果不是边界之间的内容事件, 则将 startElement替换为emptyElement并完全取消endElement 。 对不起评论不好,我稍后会回来让它更容易理解。
public class EmptyTagXMLStreamWriter extends StreamWriterDelegate {
class Event {
Method m;
Object[] args;
}
enum EventEnum {
writeStartElement,
writeAttribute,
writeNamespace,
writeEndElement,
setPrefix,
setDefaultNamespace,
}
private List<Event> queue = new ArrayList<Event>();
protected EmptyTagXMLStreamWriter(XMLStreamWriter out) {
super(out);
}
@Override
public void writeStartElement(String localName) throws XMLStreamException {
d(e(m("writeStartElement",String.class)), localName);
}
@Override
public void writeStartElement(String namespaceURI, String localName) throws XMLStreamException
{
d(e(m("writeStartElement",String.class,String.class)), namespaceURI, localName);
}
@Override
public void writeStartElement(String prefix, String localName, String namespaceURI) throws XMLStreamException
{
d(e(m("writeStartElement",String.class,String.class,String.class)), prefix, localName, namespaceURI);
}
@Override
public void writeAttribute(String localName, String value)
throws XMLStreamException {
d(e(m("writeAttribute",String.class, String.class)), localName, value);
}
@Override
public void writeAttribute(String namespaceURI, String localName,
String value) throws XMLStreamException {
d(e(m("writeAttribute",String.class, String.class, String.class)), namespaceURI, localName, value);
}
@Override
public void writeAttribute(String prefix, String namespaceURI,
String localName, String value) throws XMLStreamException {
d(e(m("writeAttribute",String.class, String.class, String.class, String.class)), prefix, namespaceURI, localName, value);
}
@Override
public void writeCData(String data) throws XMLStreamException {
fq();
super.writeCData(data);
}
@Override
public void writeCharacters(char[] text, int start, int len)
throws XMLStreamException {
fq();
super.writeCharacters(text, start, len);
}
@Override
public void writeCharacters(String text) throws XMLStreamException {
fq();
super.writeCharacters(text);
}
@Override
public void writeComment(String data) throws XMLStreamException {
fq();
super.writeComment(data);
}
@Override
public void writeDTD(String dtd) throws XMLStreamException {
fq();
super.writeDTD(dtd);
}
@Override
public void writeProcessingInstruction(String target)
throws XMLStreamException {
fq();
super.writeProcessingInstruction(target);
}
@Override
public void writeProcessingInstruction(String target, String data)
throws XMLStreamException {
fq();
super.writeProcessingInstruction(target, data);
}
@Override
public void writeNamespace(String prefix, String namespaceURI)
throws XMLStreamException {
d(e(m("writeNamespace",String.class, String.class)), prefix, namespaceURI);
}
@Override
public void writeEndElement() throws XMLStreamException {
d(e(m("writeEndElement")));
}
@Override
public void writeEndDocument() throws XMLStreamException {
fq();
super.writeEndDocument();
}
@Override
public void writeDefaultNamespace(String namespaceURI)
throws XMLStreamException {
super.writeDefaultNamespace(namespaceURI);
}
@Override
public void flush() throws XMLStreamException {
if(queue.isEmpty())
super.flush();
}
@Override
public void close() throws XMLStreamException {
fq();
out.close();
}
@Override
public void setPrefix(String prefix, String uri) throws XMLStreamException {
d(e(m("setPrefix", String.class, String.class)), prefix, uri);
}
@Override
public void setDefaultNamespace(String uri) throws XMLStreamException {
d(e(m("setDefaultNamespace", String.class)), uri);
}
void d(Event e,Object...args) throws XMLStreamException {
e.args = args;
switch(EventEnum.valueOf(e.m.getName()))
{
case writeStartElement:
fq();
queue.add(e);
break;
case writeAttribute:
case writeNamespace:
case setPrefix:
case setDefaultNamespace:
if(!queue.isEmpty())
queue.add(e);
else
ex(e, args);
break;
case writeEndElement:
if(!queue.isEmpty())
{
final Event e1 = queue.get(0);
e1.m = m("writeEmptyElement", e1.m.getParameterTypes());
fq();
}
else
{
ex(e, args);
}
break;
}
}
Event e(Method m,Object...params)
{
final Event e = new Event();
e.m = m;
e.args = params;
return e;
}
Method m(String methodName,Class<?>...args) throws XMLStreamException {
try {
return XMLStreamWriter.class.getMethod(methodName, args);
} catch (Exception e) {
throw new XMLStreamException(e);
}
}
void fq() throws XMLStreamException
{
for(int i = 0;i < queue.size();i++)
{
Event e = queue.get(i);
ex(e, e.args);
}
queue.clear();
}
void ex(Event e,Object...args) throws XMLStreamException
{
try
{
e.m.invoke(super.out, e.args);
}
catch(Exception ex)
{
throw new XMLStreamException(ex);
}
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.