diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/xml/StaxEventItemWriter.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/xml/StaxEventItemWriter.java index 242f16144..45ca9858c 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/xml/StaxEventItemWriter.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/xml/StaxEventItemWriter.java @@ -32,6 +32,7 @@ import javax.xml.stream.XMLEventWriter; import javax.xml.stream.XMLOutputFactory; import javax.xml.stream.XMLStreamException; +import org.apache.commons.lang.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.batch.item.ExecutionContext; @@ -101,6 +102,12 @@ public class StaxEventItemWriter extends ExecutionContextUserSupport implemen // name of the root tag private String rootTagName = DEFAULT_ROOT_TAG_NAME; + // namespace prefix of the root tag + private String rootTagNamespacePrefix = ""; + + // namespace of the root tag + private String rootTagNamespace = ""; + // root element attributes private Map rootElementAttributes = null; @@ -233,6 +240,43 @@ public class StaxEventItemWriter extends ExecutionContextUserSupport implemen this.rootTagName = rootTagName; } + /** + * Get the namespace prefix of the root element. Empty by default. + * + * @return the rootTagNamespacePrefix + */ + public String getRootTagNamespacePrefix() { + return rootTagNamespacePrefix; + } + + /** + * Set the namespace prefix of the root element. If not set, the namespace + * prefix "xmlns" is used. + * + * @param rootTagNamespacePrefix the rootTagNamespacePrefix to set + */ + public void setRootTagNamespacePrefix(String rootTagNamespacePrefix) { + this.rootTagNamespacePrefix = rootTagNamespacePrefix; + } + + /** + * Get the namespace of the root element. + * + * @return the rootTagNamespace + */ + public String getRootTagNamespace() { + return rootTagNamespace; + } + + /** + * Set the namespace of the root element. If not set, no namespace is used. + * + * @param rootTagNamespace the rootTagNamespace to set + */ + public void setRootTagNamespace(String rootTagNamespace) { + this.rootTagNamespace = rootTagNamespace; + } + /** * Get attributes of the root element. * @@ -386,7 +430,10 @@ public class StaxEventItemWriter extends ExecutionContextUserSupport implemen writer.add(factory.createStartDocument(getEncoding(), getVersion())); // write root tag - writer.add(factory.createStartElement("", "", getRootTagName())); + writer.add(factory.createStartElement(getRootTagNamespacePrefix(), getRootTagNamespace(), getRootTagName())); + if (!StringUtils.isBlank(getRootTagNamespace())) { + writer.add(factory.createNamespace(getRootTagNamespacePrefix(), getRootTagNamespace())); + } // write root tag attributes if (!CollectionUtils.isEmpty(getRootElementAttributes())) { @@ -411,9 +458,10 @@ public class StaxEventItemWriter extends ExecutionContextUserSupport implemen // writer.writeEndDocument(); <- this doesn't work after restart // we need to write end tag of the root element manually - + + String nsPrefix = StringUtils.isBlank(getRootTagNamespacePrefix()) ? "" : getRootTagNamespacePrefix() + ":"; try { - bufferedWriter.write(""); + bufferedWriter.write(""); } catch (IOException ioe) { throw new DataAccessResourceFailureException("Unable to close file resource: [" + resource + "]", ioe); diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/xml/StaxEventItemWriterTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/xml/StaxEventItemWriterTests.java index 412aae8c1..d72d5cd08 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/xml/StaxEventItemWriterTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/xml/StaxEventItemWriterTests.java @@ -272,8 +272,10 @@ public class StaxEventItemWriterTests { StaxResult staxResult = (StaxResult) result; try { - staxResult.getXMLEventWriter().add(XMLEventFactory.newInstance().createStartElement("", "", graph.toString())); - staxResult.getXMLEventWriter().add(XMLEventFactory.newInstance().createEndElement("", "", graph.toString())); + staxResult.getXMLEventWriter().add( + XMLEventFactory.newInstance().createStartElement("", "", graph.toString())); + staxResult.getXMLEventWriter().add( + XMLEventFactory.newInstance().createEndElement("", "", graph.toString())); } catch (XMLStreamException e) { throw new RuntimeException("Exception while writing to output file", e); @@ -315,4 +317,38 @@ public class StaxEventItemWriterTests { return source; } + + /** + * Item is written to the output file with namespace. + */ + @Test + public void testWriteRootTagWithNamespace() throws Exception { + writer.setRootTagNamespace("http://www.springframework.org/test"); + writer.open(executionContext); + writer.write(items); + writer.close(); + String content = getOutputFileContent(); + assertTrue("Wrong content: " + content, content + .contains((""))); + assertTrue("Wrong content: " + content, content.contains(TEST_STRING)); + assertTrue("Wrong content: " + content, content.contains((""))); + } + + /** + * Item is written to the output file with namespace and prefix. + */ + @Test + public void testWriteRootTagWithNamespaceAndPrefix() throws Exception { + writer.setRootTagNamespacePrefix("ns"); + writer.setRootTagNamespace("http://www.springframework.org/test"); + writer.open(executionContext); + writer.write(items); + writer.close(); + String content = getOutputFileContent(); + assertTrue("Wrong content: " + content, content + .contains((""))); + assertTrue("Wrong content: " + content, content.contains(TEST_STRING)); + assertTrue("Wrong content: " + content, content.contains((""))); + } + }