Подтвердить что ты не робот

XMLStreamWriter: отступы

нет способа напрямую писать форматированный XML, используя javax.xml.stream.XMLStreamWriter(Java SE 6)??? Это действительно невероятно, поскольку другие XML-API, такие как 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 только для красивой печати

4b9b3361

Ответ 1

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

for(int x=0; x<depth; x++) {
    xmlStreamWriter.writeCharacters("    ");
}

Ответ 2

Этот точный question ответил несколько месяцев назад, а один из ответов - использовать класс IndentingXMLStreamWriter:

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

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

Ответ 3

С 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>

Ответ 4

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

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

а Serializer предоставляет все свойства вывода, определенные XSLT (включая "отступ" ), а также некоторые саксонские.

Ответ 5

У меня нет ответа с учетом свойства "{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));
}

Ответ 6

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