XMLStreamWriter: отступы



Действительно ли нет способа напрямую написать форматированный XML с помощью javax.XML.поток.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 только для красивой печати??

585   6  

6 ответов:

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

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

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

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

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

С весны партия этого требует подкласс поскольку Джира партии-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>

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

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

И сериализатор предоставляет все XSLT-определенные выходные свойства (включая "отступ") плюс некоторые специфические для Саксона.

У меня нет ответа, учитывая свойство "{http://xml.apache.org/xslt}indent-amount". Но вы можете использовать трансформаторы несколько портативно без необходимости переделывать весь выход. Вы можете использовать что-то вроде кода ниже, чтобы создать pretty-printing 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));
}

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

Comments

    Ничего не найдено.