如何在Woodstox中使用writeRaw复用XML片段并实现缩进格式化?
嗨,这个问题我刚好研究过,给你几个不用把整个XML字符串塞进内存,就能实现带缩进的重复元素输出的可行方案:
方案1:Woodstox自带缩进配置 + 预序列化重复元素(轻量内存占用)
Woodstox本身就支持缩进输出,你可以先给XMLStreamWriter配置好缩进参数,提前把重复元素序列化成带正确缩进的小片段存起来,之后用writeRaw()输出时,这些片段自带的缩进就能和主文档格式统一,而且单个元素的内存占用非常小。
具体步骤和代码示例:
// 1. 预生成带缩进的重复元素片段 XMLOutputFactory factory = WstxOutputFactory.newInstance(); // 配置缩进参数:缩进用两个空格,自动处理空元素 factory.setProperty(WstxOutputFactory.P_INDENT_STRING, " "); factory.setProperty(WstxOutputFactory.P_AUTOMATIC_EMPTY_ELEMENTS, true); // 用ByteArrayOutputStream暂存单个重复元素(内存占用极低) ByteArrayOutputStream baos = new ByteArrayOutputStream(); XMLStreamWriter tempWriter = factory.createXMLStreamWriter(baos, "UTF-8"); // 写入你要复用的元素,比如<user>节点 tempWriter.writeStartElement("user"); tempWriter.writeAttribute("id", "123"); tempWriter.writeCharacters("John Doe"); tempWriter.writeEndElement(); tempWriter.flush(); tempWriter.close(); // 保存这个带缩进的可复用片段 String reusableUserElement = baos.toString("UTF-8"); // 2. 主文档写入时直接复用片段 XMLStreamWriter mainWriter = factory.createXMLStreamWriter(System.out, "UTF-8"); mainWriter.writeStartDocument(); mainWriter.writeStartElement("users"); // 循环输出预生成的元素,格式和主文档完全统一 for (int i = 0; i < 5; i++) { mainWriter.writeRaw(reusableUserElement); } mainWriter.writeEndElement(); mainWriter.writeEndDocument(); mainWriter.close();
方案2:自定义包装XMLStreamWriter,增强writeRaw()的缩进能力
如果不想预生成带缩进的片段,你可以自己写一个XMLStreamWriter的包装类,让它在调用writeRaw()时,根据当前文档的缩进深度自动添加缩进字符,完全动态适配主文档格式。
简化的包装类代码:
public class IndentingRawXMLStreamWriter implements XMLStreamWriter { private final XMLStreamWriter delegate; private final String indent; private int indentDepth = 0; public IndentingRawXMLStreamWriter(XMLStreamWriter delegate, String indent) { this.delegate = delegate; this.indent = indent; } // 跟踪缩进深度:开始元素时加1,结束元素时减1 @Override public void writeStartElement(String localName) throws XMLStreamException { delegate.writeStartElement(localName); indentDepth++; } @Override public void writeEndElement() throws XMLStreamException { indentDepth--; delegate.writeEndElement(); } // 重写writeRaw,自动添加当前级别的缩进 @Override public void writeRaw(String data) throws XMLStreamException { // 写入对应深度的缩进 for (int i = 0; i < indentDepth; i++) { delegate.writeCharacters(indent); } delegate.writeRaw(data); // 可选:添加换行保持文档格式一致性 delegate.writeCharacters("\n"); } // 其他所有XMLStreamWriter方法直接委托给原始writer即可 @Override public void writeAttribute(String localName, String value) throws XMLStreamException { delegate.writeAttribute(localName, value); } // 省略其他方法的委托实现... }
使用时只需要把Woodstox的writer包装一下:
XMLOutputFactory factory = WstxOutputFactory.newInstance(); XMLStreamWriter rawWriter = factory.createXMLStreamWriter(System.out, "UTF-8"); // 包装成支持缩进的writer,指定缩进用两个空格 IndentingRawXMLStreamWriter indentingWriter = new IndentingRawXMLStreamWriter(rawWriter, " "); indentingWriter.writeStartDocument(); indentingWriter.writeStartElement("users"); // 直接传入不带缩进的原始元素片段,包装类会自动处理缩进 String rawUser = "<user id=\"123\">John Doe</user>"; for (int i = 0; i < 5; i++) { indentingWriter.writeRaw(rawUser); } indentingWriter.writeEndElement(); indentingWriter.writeEndDocument(); indentingWriter.close();
注意事项
- 确保使用最新版本的Woodstox,避免旧版本的缩进相关bug
- 如果重复元素包含特殊字符(比如
&、<),要保证预生成或传入writeRaw()的内容是合法的XML片段,避免格式错误
内容的提问来源于stack exchange,提问作者Mathias
相关产品推荐
相关产品推荐

