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 только для красивой печати??
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-printingXMLStreamWriter.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