使用StaxEventItemWriter构建非平凡的XML文件

我需要使用这种结构将一些数据库表的内容转储到XML文件

    value value value  ...  
...

每个表的未知记录的实际数量,因此我无法将单个表的所有数据存储在内存中并转储到XML。
我现在的工作定义为:


                                       RecordBean    

 public class RecordBeanRowMapper implements RowMapper { final static RowMapper<Map> columnMapRowMapper = new ColumnMapRowMapper(); private String tableName; public void setTableName(String tableName) { this.tableName = tableName; } @Override public RecordBean mapRow(ResultSet rs, int rowNum) throws SQLException { final RecordBean b = new RecordBean(); b.setTableName(tableName); b.setColumnValues(Maps.transformValues(columnMapRowMapper.mapRow(rs, rowNum), new Function() { @Override public String apply(Object input) { return (input == null ? "NULL" : input.toString(); } } } @XmlAccessorType(XmlAccessType.FIELD) @XmlRootElement(namespace="") class RecordBean { private String tableName; @XmlJavaTypeAdapter /* Entries are written using an adapter to write data as * value * value * ... */ public Map entries = new HashMap(); } /* Use to build item node name using dynamic tableName as *  * value * value *  */ public class RecordBeanToJaxbElementProcessor implements ItemProcessor<RecordBean, JAXBElement> { @Override public JAXBElement process(RecordBean item) throws Exception { return new JAXBElement(new QName(item.getTableName()), RecordBean.class, item); } } 

这项工作不完整,不能满足我的需求,因为输出看起来像

    Code one A record xyz NULL false false 
Code 2 Another record no_name

我想我必须丰富作家和/或marshaller组件来实现我的目标,但我还没有找到一个好的方法来继续:(

我的问题是:
如何在开始时描述构建复杂的XML结构并使作业完全可重新启动并且内存使用量很少?

[摘自spring.io论坛]
这不是默认的StaxEventItemWriter。 我必须为我的一个项目做类似的事情,并编写了一个自定义的GroupingStaxEventItemWriter。 请参阅下面的代码。 您需要为特定用例修改openGroup和closeGroup方法。 请注意,通过直接写入底层java.io.Writer而不是通过XMLEventWriter来关闭分组标记。 这是可重启性所必需的。

 public class GroupingStaxEventItemWriter extends StaxEventItemWriter { private static final String GROUP_IDENTIFIER = "CURRENT_GROUP"; private Classifier classifier; private String currentGroup; private XMLEventWriter eventWriter; private Writer writer; @Override public void write(List items) throws XmlMappingException, Exception { Map> itemsGroup = new LinkedHashMap>(); for (T item : items) { String group = classifier.classify(item); if (!itemsGroup.containsKey(group)) { itemsGroup.put(group, new ArrayList()); } itemsGroup.get(group).add(item); } for (String group : itemsGroup.keySet()) { if (group == null || !group.equals(currentGroup)) { if (currentGroup != null) { closeGroup(currentGroup); } currentGroup = group; if (currentGroup != null) { openGroup(currentGroup); } } super.write(itemsGroup.get(group)); } } protected void openGroup(String group) throws XMLStreamException, FactoryConfigurationError { String groupTagName = group; String groupTagNameSpacePrefix = ""; String groupTagNameSpace = null; if (groupTagName.contains("{")) { groupTagNameSpace = groupTagName.replaceAll("\\{(.*)\\}.*", "$1"); groupTagName = groupTagName.replaceAll("\\{.*\\}(.*)", "$1"); if (groupTagName.contains(":")) { groupTagNameSpacePrefix = groupTagName.replaceAll("(.*):.*", "$1"); groupTagName = groupTagName.replaceAll(".*:(.*)", "$1"); } } XMLEventFactory xmlEventFactory = createXmlEventFactory(); eventWriter.add(xmlEventFactory.createStartElement(groupTagNameSpacePrefix, groupTagNameSpace, groupTagName)); } protected void closeGroup(String group) throws XMLStreamException, FactoryConfigurationError { String groupTagName = group; String groupTagNameSpacePrefix = ""; if (groupTagName.contains("{")) { groupTagName = groupTagName.replaceAll("\\{.*\\}(.*)", "$1"); if (groupTagName.contains(":")) { groupTagNameSpacePrefix = groupTagName.replaceAll("(.*):.*", "$1") + ":"; groupTagName = groupTagName.replaceAll(".*:(.*)", "$1"); } } try { writer.write(""); } catch (IOException ioe) { throw new DataAccessResourceFailureException("Unable to close group: [" + group + "]", ioe); } } @Override protected XMLEventWriter createXmlEventWriter(XMLOutputFactory outputFactory, Writer writer) throws XMLStreamException { this.writer = writer; this.eventWriter = super.createXmlEventWriter(outputFactory, writer); return eventWriter; } @Override public void open(ExecutionContext executionContext) { if (executionContext.containsKey(getExecutionContextKey(GROUP_IDENTIFIER))) { currentGroup = executionContext.getString(getExecutionContextKey(GROUP_IDENTIFIER)); } super.open(executionContext); } @Override public void update(ExecutionContext executionContext) { executionContext.putString(getExecutionContextKey(GROUP_IDENTIFIER), currentGroup); super.update(executionContext); } @Override public void close() { if (currentGroup != null) { try { closeGroup(currentGroup); } catch (XMLStreamException e) { throw new ItemStreamException("Failed to write close tag for element: " + currentGroup, e); } catch (FactoryConfigurationError e) { throw new ItemStreamException("Failed to write close tag for element: " + currentGroup, e); } } super.close(); } @Override public void afterPropertiesSet() throws Exception { super.afterPropertiesSet(); Assert.notNull(classifier, "Missing required property 'classifier'"); } public void setClassifier(Classifier classifier) { this.classifier = classifier; } }