XMLStreamWriter:缩进

Puc*_*uce 32 java xml

是否真的没有办法直接使用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);
Run Code Online (Sandbox Code Playgroud)

此解决方案的问题是属性"{http://xml.apache.org/xslt}indent-amount".我没有找到任何关于它的文档,它似乎不保证是可移植的.

那么,如果我想用标准的Java 6类做什么,我还有什么其他选择?创建一个JAXB或DOM对象图只是为了漂亮的打印?

Tom*_*vic 36

几个月前已经回答了这个确切的问题,其中一个答案是使用IndentingXMLStreamWriter类:

XMLOutputFactory xmlof = XMLOutputFactory.newInstance();
XMLStreamWriter writer = new IndentingXMLStreamWriter(xmlof.createXMLStreamWriter(out));
Run Code Online (Sandbox Code Playgroud)

就代码而言,它是一个简洁的解决方案,但要小心:这是一个com.sun.*类,不能保证其一般可用性......

  • 正如您所说,不幸的是,这不是已发布的 API。 (2认同)
  • `IndentingXMLStreamWriter` 类及其基类 `DelegatingXMLStreamWriter` 可以使用反编译器(IntelliJ IDEA 现在有一个内置的)打开,并以源代码形式保存为我们自己项目的一部分。因此,他们的“未发表”并不是真正的问题。如果这样做,请务必修复 sun 代码中的错误:在 `onEmptyElement()` 方法中,对 `writeCharacters( "\n" );` 的调用应该是 `super.writeCharacters( "\n" ); ` 相反。 (2认同)

bdo*_*han 8

您可以在writeXml方法中添加必要的代码来格式化文档.只需保持深度计数器(以指示嵌套水平).然后在writeStartElement之前和writeEndElement之后使用深度索引来插入缩进.

for(int x=0; x<depth; x++) {
    xmlStreamWriter.writeCharacters("    ");
}
Run Code Online (Sandbox Code Playgroud)

  • 我想我必须在任何 writeXYZ 调用(例如使用包装器)之前调用它,并且如您所说,管理深度。可能可行,但不像 JAXB 那样微不足道: marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true); (2认同)