Java XMLStreamWriter:缩进

Java XMLStreamWriter:缩进,java,xml,Java,Xml,是否真的没有办法使用javax.XML.stream.XMLStreamWriter(JavaSE6)直接编写格式化的XML???这真是难以置信,因为其他XML API(如JAXB和一些DOM库)能够做到这一点。即使是与.NET XMLStreamWriter等效的程序也可以实现这个AFAIK(如果我没记错的话,这个类是System.Xml.XmlTextWriter) 这意味着我唯一的选择是重新分析XML以生成格式化输出 例如: 此解决方案的问题在于“属性”{http://xml.apache

是否真的没有办法使用javax.XML.stream.XMLStreamWriter(JavaSE6)直接编写格式化的XML???这真是难以置信,因为其他XML API(如JAXB和一些DOM库)能够做到这一点。即使是与.NET XMLStreamWriter等效的程序也可以实现这个AFAIK(如果我没记错的话,这个类是System.Xml.XmlTextWriter)

这意味着我唯一的选择是重新分析XML以生成格式化输出

例如:

此解决方案的问题在于“属性”{http://xml.apache.org/xslt}缩进金额”。我没有找到任何关于它的文档,而且似乎也不能保证它是可移植的


那么,如果我想用标准Java6类实现这一点,我还有什么其他选择呢?创建一个JAXB或DOM对象图只是为了进行漂亮的打印???

您可以添加必要的代码以在writeXml方法中格式化文档。只需维护一个深度计数器(以指示嵌套的级别)。然后在WriteStarteElement之前和WriteDelete之后,使用深度索引插入缩进

for(int x=0; x<depth; x++) {
    xmlStreamWriter.writeCharacters("    ");
}

for(int x=0;x标准java.xml接口对序列化几乎没有控制是正确的,即使底层实现(Apache Xerces)是的。我必须解决这个问题,我想到的最好办法是包含Xerces的一个副本,并使用
org.apache.xml.serialize
类。

几个月前就已经回答了这个问题,就是使用IndentingXMLStreamWriter类:

XMLOutputFactory xmlof = XMLOutputFactory.newInstance();
XMLStreamWriter writer = new IndentingXMLStreamWriter(xmlof.createXMLStreamWriter(out));

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

对于Spring Batch,这需要一个子类,因为

公共类缩进TaxeventionItemWriter扩展了StatxeventionItemWriter{
@塞特
@吸气剂
私有布尔缩进=真;
@凌驾
受保护的XMLEventWriter createXmlEventWriter(XMLOutputFactory outputFactory,Writer-Writer)抛出XMLStreamException{
if(isIndenting()){
返回新的缩进XMLEventWriter(super.createXmlEventWriter(outputFactory,writer));
}
否则{
返回super.createXmlEventWriter(outputFactory,writer);
}
}
}
但这需要额外的依赖关系,因为Spring批处理不包括缩进StAX输出的代码:

<dependency>
  <groupId>net.java.dev.stax-utils</groupId>
  <artifactId>stax-utils</artifactId>
  <version>20070216</version>
</dependency>

net.java.dev.stax-utils
斯塔克斯乌提尔斯酒店
20070216

作为记录,Saxon允许您通过s9api接口获取序列化XMLStreamWriter:

Processor p = new Processor();
Serializer s = p.newSerializer();
s.setOutputProperty(Property.INDENT, "yes");
XMLStreamWriter w = s.getXMLStreamWriter();

序列化程序公开所有XSLT定义的输出属性(包括“缩进”)以及一些特定于Saxon的属性。

考虑到
,我没有答案{http://xml.apache.org/xslt}“缩进金额”
property。但是您可以在某种程度上方便地使用transformers,而无需重新分析所有输出。您可以使用下面的代码创建漂亮的打印
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));
}

我找不到这样的writeText方法?!你是对的,它应该是writeCharacters。此方法可用于在文档中的任何位置插入文本,而不仅仅是在单个元素中。我想我必须在任何writeXYZ调用之前调用此方法(例如,使用包装器)并且,正如您所说,管理深度。可能是可行的,但不像JAXB:marshaller.setProperty(marshaller.JAXB_格式化的_输出,true)那样简单;是的,我读过关于此类解决方案的文章,但自从Xerces 2.9.0以来,这个软件包就被弃用了:有趣的部分是stax utils库,它提供了IndentingXMLEventWriter,似乎独立于Spring Batch。感谢您的提示!正如您所说,不幸的是,这不是一个已发布的API。
IndentingXMLStreamWriter
class及其基类
DelegatingXMLStreamWriter
可以用反编译器打开(IntelliJ IDEA现在有一个内置的)并以源代码形式保存为我们自己项目的一部分。因此,它们的“未发布”并不是一个真正的问题。如果你这样做,一定要修复sun代码中的一个错误:
Onemptylement()
method,调用
writeCharacters(“\n”);
应该是
super.writeCharacters(“\n”);
相反。这里有一个稍微完整的版本:最后一行导致:
java.lang.UnsupportedOperationException:类型为javax.xml.transform.sax的结果。SAXResult@184f6be2不支持。支持的结果类型有:DOMResult、StAXResult和StreamResult
。我们使用Java版本1.8u74,你呢?我认为它应该在ng实现是Apache Xerces,但不能保证与其他实现一起工作……请原谅,什么是
writeXml()
?最好提供您代码的所有必要部分,以便您可以在遇到与您相同的问题时尝试(我的情况),但我不知道它是什么(背后是什么代码)不幸的是,我无法尝试。
Processor p = new Processor();
Serializer s = p.newSerializer();
s.setOutputProperty(Property.INDENT, "yes");
XMLStreamWriter w = s.getXMLStreamWriter();
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));
}