[英]XMLStreamWriter: indentation
是否真的没有办法直接使用javax.xml.stream.XMLStreamWriter(Java SE 6)编写格式化的XML? 这真是令人难以置信,因为其他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对象图只是为了漂亮的打印?
您可以在writeXml方法中添加必要的代码来格式化文档。 只需保持深度计数器(以指示嵌套水平)。 然后在writeStartElement之前和writeEndElement之后使用深度索引来插入缩进。
for(int x=0; x<depth; x++) {
xmlStreamWriter.writeCharacters(" ");
}
使用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>
只是为了记录,Saxon允许您通过s9api接口获取序列化XMLStreamWriter:
Processor p = new Processor();
Serializer s = p.newSerializer();
s.setOutputProperty(Property.INDENT, "yes");
XMLStreamWriter w = s.getXMLStreamWriter();
并且Serializer公开了所有XSLT定义的输出属性(包括“缩进”)以及一些特定于Saxon的输出属性。
考虑到"{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));
}
你是正确的,标准的java.xml接口几乎不提供对序列化的控制,即使底层实现(Apache Xerces)也是如此。 我必须解决这个问题,我提出的最好的方法是包含一个Xerces副本并使用org.apache.xml.serialize
类。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.