JAXB упорядочивает XML по-другому к OutputStream по сравнению с StringWriter

Я приношу извинения, если этому ответили, но критерии поиска, которые я использовал (т.е. сжатый JAXB @XmlAttribute или маршал JAXB XML для Строкового представления различных результатов) ничего не придумывают.

Я использую JAXB для объектов ООН/маршала, аннотируемых @XmlElement и @XmlAttribute аннотации. У меня есть класс средства форматирования, который предоставляет два метода - каждый переносит метод маршала и принимает объект упорядочить и OutputStream, другой просто принимает объект и возвращает вывод XML как Строку. К сожалению, эти методы не обеспечивают тот же вывод для тех же объектов. При маршалинге в файл, поля простого объекта, внутренне отмеченные с @XmlAttribute печатаются как:

<element value="VALUE"></element>

в то время как при маршалинге к Строке, они:

<element value="VALUE"/>

Я предпочел бы второй формат для обоих случаев, но мне любопытно относительно того, как управлять различием и согласился бы на них являющийся тем же независимо. Я даже создал один статический marshaller что оба использования методов для устранения различных значений экземпляра. Форматирование код следует:

/** 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>
12
задан Daniel Szalay 30 April 2012 в 15:27
поделиться

4 ответа

Похоже, это может быть «ошибка» в 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-ri \ runtime \ src \ com \ sun \ xml \ bind \ v2 \ runtime \ MarshallerImpl.java.

Вы создаете два писателя:

jaxb-ri \ runtime \ src \ com \ sun \ xml \ bind \ v2 \ runtime \ output \ UTF8XmlOutput.java

jaxb-ri \ runtime \ src \ com \ sun \ xml \ bind \ v2 \ runtime \ output \ XMLStreamWriterOutput.java

8
ответ дан 2 December 2019 в 22:04
поделиться

Я не знаю, почему JAXB делает это - или даже если это JAXB - если JAXB выводит XML, например, через SAXContentHandler, то он не имеет прямого контроля над тем, насколько близки теги произведено.

Чтобы добиться согласованного поведения, вы можете заключить свой 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 , чтобы попытаться сделать вывод как можно короче. Звучит маловероятно, но у меня нет другого объяснения.

1
ответ дан 2 December 2019 в 22:04
поделиться

Почему это важно? эквивалентно в xml

0
ответ дан 2 December 2019 в 22:04
поделиться

Хорошая новость в том, что JAXB - это спецификация с более чем одной реализацией (как и JPA). Если одна реализация не соответствует вашим потребностям, доступны другие, например EclipseLink JAXB (MOXy):

2
ответ дан 2 December 2019 в 22:04
поделиться
Другие вопросы по тегам:

Похожие вопросы: