JAXB以不同的方式将XML封送到OutputStream与StringWriter

And*_*ndy 12 java xml java-metro-framework jaxb

我很抱歉,如果这已经得到解答,但我一直在使用的搜索术语(即JAXB @XmlAttribute压缩JAXB XML编组到String不同的结果)没有提出任何建议.

我正在使用JAXB来取消/编组带注释@XmlElement@XmlAttribute注释的对象.我有一个格式化程序类,它提供了两个方法 - 一个包装marshal方法并接受对象编组和一个OutputStream,另一个只接受对象并将XML输出作为String返回.不幸的是,这些方法不能为相同的对象提供相同的输出.封送到文件时,内部标记的简单对象字段@XmlAttribute将打印为:

<element value="VALUE"></element>
Run Code Online (Sandbox Code Playgroud)

当编组到一个字符串时,它们是:

<element value="VALUE"/>
Run Code Online (Sandbox Code Playgroud)

我更喜欢这两种情况的第二种格式,但我很好奇如何控制差异,并且无论如何都会满足于它们.我甚至创建了一个静态编组器,两种方法都使用它来消除不同的实例值.格式代码如下:

/** Marker interface for classes which are listed in jaxb.index */
public interface Marshalable {}
Run Code Online (Sandbox Code Playgroud)
/** Local exception class */
public class XMLMarshalException extends BaseException {}
Run Code Online (Sandbox Code Playgroud)
/** 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);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)
/** Example data */
@XmlType
@XmlAccessorType(XmlAccessType.FIELD)
public class Data {

    @XmlAttribute(name = value)
    private String internalString;
}
Run Code Online (Sandbox Code Playgroud)
/** 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;
}
Run Code Online (Sandbox Code Playgroud)

调用的结果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>
Run Code Online (Sandbox Code Playgroud)

输出到字符串

<?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>
Run Code Online (Sandbox Code Playgroud)

Eri*_*sen 8

看起来这可能是JAXB中的"bug".查看源代码,调用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));
}
Run Code Online (Sandbox Code Playgroud)

关于它们如何处理"空元素",编写器的实现是不同的.以上代码来自:

JAXB里\运行的\ src\COM \太阳\ XML \绑定\ V2 \运行\ MarshallerImpl.java.

你正在创作的两位作家是:

JAXB里\运行的\ src\COM \太阳\ XML \绑定\ V2 \运行\输出\ UTF8XmlOutput.java

JAXB里\运行的\ src\COM \太阳\ XML \绑定\ V2 \运行\输出\ XMLStreamWriterOutput.java

  • 更准确地说,这是Metro JAXB实现中的一个错误.其他JAXB实现(如EclipseLink JAXB(MOXy))没有此错误. (5认同)