XMLStreamWriter: отступ - PullRequest
       21

XMLStreamWriter: отступ

30 голосов
/ 06 января 2011

действительно ли нет способа напрямую писать отформатированный XML с использованием javax.xml.stream.XMLStreamWriter (Java SE 6) ??? Это действительно невероятно, так как другие API XML, такие как JAXB и некоторые библиотеки DOM, могут это сделать. Даже .NET XMLStreamWriter эквивалентен этому AFAIK (если я правильно помню, класс System.Xml.XmlTextWriter).

Это означает, что единственный вариант, который у меня есть, - это повторный анализ XML для генерации форматированного вывода ??

например:.

            StringWriter sw = new StringWriter();
    XMLOutputFactory xmlOutputFactory = XMLOutputFactory.newFactory();
    XMLStreamWriter xmlStreamWriter = xmlOutputFactory.createXMLStreamWriter(sw);
    writeXml(xmlStreamWriter);
    xmlStreamWriter.flush();
    xmlStreamWriter.close();

    TransformerFactory factory = TransformerFactory.newInstance();

    Transformer transformer = factory.newTransformer();
    transformer.setOutputProperty(OutputKeys.INDENT, "yes");
    transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "4");

    StringWriter formattedStringWriter = new StringWriter();
    transformer.transform(new StreamSource(new StringReader(sw.toString())), new StreamResult(formattedStringWriter));
    System.out.println(formattedStringWriter);

Проблема с этим решением заключается в свойстве "{http://xml.apache.org/xslt}indent-amount". Я не нашел никакой документации по нему, и, похоже, он не является переносимым.

Итак, какие еще варианты у меня есть, если я хочу сделать это со стандартными классами Java 6? Создать граф объектов JAXB или DOM только для красивой печати ??

Ответы [ 6 ]

35 голосов
/ 17 июля 2011

На этот точный вопрос был дан ответ несколько месяцев назад, и один из ответов заключается в использовании класса IndentingXMLStreamWriter:

XMLOutputFactory xmlof = XMLOutputFactory.newInstance();
XMLStreamWriter writer = new IndentingXMLStreamWriter(xmlof.createXMLStreamWriter(out));

Это правильное решениечто касается кода, но осторожно: это класс com.sun. *, его общая доступность не гарантируется ...

8 голосов
/ 06 января 2011

Вы можете добавить необходимый код для форматирования документа с помощью метода writeXml . Просто ведите счетчик глубины (чтобы указать уровни вложенности). Затем перед записьюStartElement и после записиEndElement используйте индекс глубины для вставки отступа.

for(int x=0; x<depth; x++) {
    xmlStreamWriter.writeCharacters("    ");
}
2 голосов
/ 24 ноября 2016

У меня нет ответа, учитывая "{http://xml.apache.org/xslt}indent-amount" свойство.Но вы можете использовать трансформаторы несколько портативно без необходимости повторной обработки всех выходных данных.Вы можете использовать что-то вроде кода ниже, чтобы создать симпатичную печать XMLStreamWriter.

public static void main(String[] args) {
    XMLStreamWriter xmlStreamWriter = createXMLStreamWriter(new OutputStreamWriter(System.out));
    writeXml(xmlStreamWriter);
}

private static XMLStreamWriter createXMLStreamWriter(Writer textWriter) throws XMLStreamException {
    SAXTransformerFactory xmlTransformerFactory = (SAXTransformerFactory)SAXTransformerFactory.newInstance();
    TransformerHandler transformingSAXHandler;
    try {
        transformingSAXHandler = xmlTransformerFactory.newTransformerHandler();
    } catch (TransformerConfigurationException e) {
        throw new XMLStreamException(e);
    }
    Transformer xmlTransformer = transformingSAXHandler.getTransformer();
    xmlTransformer.setOutputProperty(OutputKeys.INDENT, "yes");
    transformingSAXHandler.setResult(new StreamResult(textWriter));

    XMLOutputFactory xmlOutputFactory = XMLOutputFactory.newInstance();
    return xmlOutputFactory.createXMLStreamWriter(new SAXResult(transformingSAXHandler));
}
2 голосов
/ 10 марта 2014

Только для записи, Saxon позволяет вам получить сериализацию XMLStreamWriter через интерфейс s9api:

Processor p = new Processor();
Serializer s = p.newSerializer();
s.setOutputProperty(Property.INDENT, "yes");
XMLStreamWriter w = s.getXMLStreamWriter();

, и Serializer предоставляет все свойства вывода, определенные в XSLT (включая «отступ»), а также некоторые Saxon-специфичные.

2 голосов
/ 18 сентября 2013

Для Spring Batch требуется подкласс, так как JIRA BATCH-1867

public class IndentingStaxEventItemWriter<T> extends StaxEventItemWriter<T> {

  @Setter
  @Getter
  private boolean indenting = true;

  @Override
  protected XMLEventWriter createXmlEventWriter( XMLOutputFactory outputFactory, Writer writer) throws XMLStreamException {
    if ( isIndenting() ) {
      return new IndentingXMLEventWriter( super.createXmlEventWriter( outputFactory, writer ) );
    }
    else {
      return super.createXmlEventWriter( outputFactory, writer );
    }
  }

}

Но для этого требуется дополнительная зависимость, поскольку Spring Batch не содержит код для отступа вывода StAX:

<dependency>
  <groupId>net.java.dev.stax-utils</groupId>
  <artifactId>stax-utils</artifactId>
  <version>20070216</version>
</dependency>
1 голос
/ 06 января 2011

Вы правы, что стандартные интерфейсы java.xml практически не контролируют сериализацию, даже если базовая реализация (Apache Xerces) это делает.Мне пришлось решить эту проблему, и лучшее, что я придумал, - это включить копию Xerces и использовать классы org.apache.xml.serialize.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...