XMLStreamWriter:缩进

时间:2011-01-06 15:12:32

标签: java xml

是否真的无法使用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对象图只是为了漂亮的打印?

6 个答案:

答案 0 :(得分:35)

几个月前已经回答了这个确切的questionone 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类。