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