是否真的无法使用javax.xml.stream.XMLStreamWriter(Java SE 6)直接编写格式化的XML?这真是令人难以置信,因为其他XML API(如JAXB和一些DOM库)能够做到这一点。即使.NET XMLStreamWriter等效也能够使用这个AFAIK(如果我没记错的话,该类是System.Xml.XmlTextWriter)。
这意味着我唯一的选择是重新分析XML以生成格式化输出??
E.g:
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对象图只是为了漂亮的打印?
答案 0 :(得分:35)
几个月前已经回答了这个确切的question,one of the answers是使用IndentingXMLStreamWriter类:
XMLOutputFactory xmlof = XMLOutputFactory.newInstance();
XMLStreamWriter writer = new IndentingXMLStreamWriter(xmlof.createXMLStreamWriter(out));
就代码而言,这是一个很好的解决方案,但要小心:这是一个com.sun。*类,不能保证其一般可用性......
答案 1 :(得分:8)
答案 2 :(得分:2)
使用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>
答案 3 :(得分:2)
只是为了记录,Saxon允许您通过s9api接口获取序列化XMLStreamWriter:
Processor p = new Processor();
Serializer s = p.newSerializer();
s.setOutputProperty(Property.INDENT, "yes");
XMLStreamWriter w = s.getXMLStreamWriter();
并且Serializer公开了所有XSLT定义的输出属性(包括“缩进”)以及一些特定于Saxon的输出属性。
答案 4 :(得分:2)
我没有考虑"{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));
}
答案 5 :(得分:1)
你是正确的,标准的java.xml接口几乎不提供对序列化的控制,即使底层实现(Apache Xerces)也是如此。我必须解决这个问题,我提出的最好的方法是包含一个Xerces副本并使用org.apache.xml.serialize
类。