Вопросы о формате вывода JAXB XML

У меня есть классы Java со следующей структурой (названия классов ничего не подразумевают, я их просто придумал).

package test;

import java.util.ArrayList;
import java.util.List;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlElementWrapper;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlValue;

@XmlRootElement
public class Test
{
    @XmlAccessorType(XmlAccessType.FIELD)
    static class Machine
    {
        @XmlElementWrapper(name="servers")
        @XmlElement(name="server")
        List<Server> servers = new ArrayList<Server>();
    }

    @XmlAccessorType(XmlAccessType.FIELD)
    static class Server
    {
        Threshold t = new Threshold();
    }

    @XmlAccessorType(XmlAccessType.FIELD)
    static class Threshold
    {
        RateThreshold load = new RateThreshold();
    }

    @XmlAccessorType(XmlAccessType.FIELD)
    static class RateThreshold
    {
        @XmlAccessorType(XmlAccessType.FIELD)
        static class Rate
        {
            int count;
            Period period = new Period();
        }

        @XmlAccessorType(XmlAccessType.FIELD)
        private static class Period
        {
            @XmlAttribute
            private String type = "second";

            @XmlValue
            private float period;
        }

        Rate min = new Rate();
        Rate max = new Rate();
    }

    @XmlElementWrapper(name="machines")
    @XmlElement(name="machine")
    List<Machine> machines = new ArrayList<Machine>();

    public static void main(String[] args)
    {
        Machine m = new Machine();
        Server s = new Server();
        s.t.load.max.count = 10;
        s.t.load.min.count = 1;
        m.servers.add(s);

        Test t = new Test();
        t.machines.add(m);

        JAXBContext jaxbContext;
        Marshaller marshaller;
        try
        {
            jaxbContext = JAXBContext.newInstance(Test.class);
            marshaller = jaxbContext.createMarshaller();
            marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
            marshaller.marshal(t, System.out);
        }
        catch (JAXBException e)
        {
            e.printStackTrace();
        }
    }
}

Проблема, с которой я столкнулся, связана с выводом XML, сгенерированным JAXB при маршалинге тестового экземпляра. Вывод XML всегда будет выглядеть следующим образом:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<test>
    <machines>
        <machine>
            <servers>
                <server>
                    <t>
                        <load>
                            <min>
<count>1</count>
<period type="second">0.0</period>
                            </min>
                            <max>
<count>10</count>
<period type="second">0.0</period>
                            </max>
                        </load>
                    </t>
                </server>
            </servers>
        </machine>
    </machines>
</test>

Как видите, некоторые элементы имеют неправильный отступ (то есть самые глубокие элементы, количество и период). Это почему? Что-то не так с тем, как я создал контекст JAXB? Или существует максимальный предел количества элементов, которые могут быть рекурсивно смещены JAXB? Как я мог это исправить? Обратите внимание, что я также установил для JAXB_FORMATTED_OUTPUT значение true, но все равно получаю неправильный отступ.

Спасибо.

Ответов (4)

Решение

Отступ происходит по модулю 8, в

com.sun.xml.bind.v2.runtime.output.IndentingUTF8XmlOutput

ты находишь

int i = depth%8;

Вам нужно установить ширину линии - по умолчанию 72.

Формат вывода = новый Формат вывода ();

of.setLineWidth (1000);

Одна из перегрузок marshal() метода упаковщика принимает XMLStreamWriter, поэтому вы можете обойти поврежденный мозгом механизм форматирования эталонной реализации JAXB, написав собственный модуль записи потока XML для форматирования. Вы бы сделали что-то вроде этого:

public static void SaveContainer( Container container, OutputStream stream ) throws ...
{
    XMLOutputFactory factory = XMLOutputFactory.newInstance();
    XMLStreamWriter writer = factory.createXMLStreamWriter( stream, "UTF-8" );
    writer = new MyAwesomeCoolFormattingXMLStreamWriter( writer );
    marshaller.marshal( container, writer );
}

Я не думаю, что есть предел. Я видел очень глубокое гнездование, без каких-либо трудностей. Есть ли у вас контроль пробелов? Кроме того, вы не предоставили определение класса RateThreshold, который создает неожиданный результат.