使用JAXB和XMLStreamWriter编写空标记 [英] Write empty tag with JAXB and XMLStreamWriter
问题描述
我正在使用标准的JAXB实现。
这是我的带注释的类(是一组类的一部分)
I'm using standard JAXB implementation.
This is my annotated class (is part of a set of classes)
@XmlType()
@XmlAccessorType(FIELD)
class MyClass {
@XmlValue
protected final String value = null;
@XmlAttribute
protected String attr;
...get/set for attr...
}
我正在使用
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和其他人,但我需要将对象保存到文件中)。
任何建议或解决方案?
the result is <my-class attr="attrValue"></my-class>
but I need empty tag as <my-class attr="attrValue"/>
.
I tried some different combination (and read dozen of SO questions) of writer and target stream (not only file,but also StringWriter and others but I need to persist object to file).
Any advice or solution?
推荐答案
我使用替换<的自定义XMLStreamWriter解析; tag-name>< / tag-name>
带< tag-name />
如果tag-name完全没有内容。
背后的想法是在 startElement-endElement 之间推迟写事件。
当找到 endElement 时,如果不是边界之间的内容事件,则使用 emptyElement 替换 startElement 并禁止 endElement 。
很抱歉评论不好,我稍后会回来让它更容易理解。
I resolved using a custom XMLStreamWriter that replace the <tag-name></tag-name>
with <tag-name/>
if tag-name has no content at all.
The idea behind is to defer write events between startElement-endElement.
When an endElement is found if the aren't content events between boundaries replace startElement with a emptyElement and suppress endElement at all.
Sorry for poor comments, I'll came back later to make it more understandable.
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);
}
}
}
这篇关于使用JAXB和XMLStreamWriter编写空标记的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!