So far I have worked a lot with Java and XML but mostly with the DOM parser. For my current project I had to split a big XML document into smaller 'messages' and put these small messages on a queue. Well, if you have the same experience as I do with DOM then you know that that is not going to work without a lot of available memory. So that's why I chose a SAX parser and to be more specific a StAX parser.
One thing that you have to take care of are the namespaces in the original 'batch' xml document. These namespaces can be specified in the root element and when you just 'copy' some inner XML fragments as being new XML documents you might miss these namespaces defined at a 'higher' level. For example see this batch xml-document:

XML:
  1. <?xml version="1.0" encoding="UTF-8" ?>
  2. <root-element xmlns:prefix="http://www.pascalalma.net/xml">
  3.     <xml-messages xmlns:prefix2="http://www.pascalalma.net/xml2">
  4.         <prefix:xml-message xml-attr1="msg one">
  5.             <prefix2:nr xml-attr2="one">1</prefix2:nr>
  6.             <prefix3:msg
  7.                 xmlns:prefix3="http://www.pascalalma.net/xml3">
  8.                 Message number one
  9.             </prefix3:msg>
  10.         </prefix:xml-message>
  11.         <prefix:xml-message xml-attr1="msg two">
  12.             <prefix2:nr xml-attr2="two">2</prefix2:nr>
  13.             <prefix3:msg
  14.                 xmlns:prefix3="http://www.pascalalma.net/xml3">
  15.                 Message number two
  16.             </prefix3:msg>
  17.         </prefix:xml-message>
  18.         <prefix:xml-message xml-attr1="msg three">
  19.             <prefix2:nr xml-attr2="three">3</prefix2:nr>
  20.             <prefix3:msg
  21.                 xmlns:prefix3="http://www.pascalalma.net/xml3">
  22.                 Message number three
  23.             </prefix3:msg>
  24.         </prefix:xml-message>
  25.     </xml-messages>
  26. </root-element>

What we need is a XML document for each 'prefix:xml-message'-tag we encounter. But simply copy & paste that piece of XML is not going to work because we will then miss the declaration of the 'prefix' namespace. So to avoid that I collect every namespace I encounter before I reach the 'prefix:xml-message'-tag and process this collection of namespaces into the new XML document root element. Here is the complete class doing the whole thing:

JAVA:
  1. package net.pascalalma.xml;
  2.  
  3. import java.io.InputStream;
  4. import java.io.StringWriter;
  5. import java.util.HashMap;
  6. import java.util.Iterator;
  7. import java.util.Map;
  8.  
  9. import javax.xml.namespace.QName;
  10. import javax.xml.stream.XMLInputFactory;
  11. import javax.xml.stream.XMLOutputFactory;
  12. import javax.xml.stream.XMLStreamConstants;
  13. import javax.xml.stream.XMLStreamException;
  14. import javax.xml.stream.XMLStreamReader;
  15. import javax.xml.stream.XMLStreamWriter;
  16.  
  17. import org.codehaus.stax2.XMLInputFactory2;
  18. import org.codehaus.stax2.XMLOutputFactory2;
  19.  
  20.  
  21. public class StaxParser {
  22.  
  23.    private static final QName MSG_TAG = new QName("http://www.pascalalma.net/xml", "xml-message");
  24.    private static final String ENCODING = "UTF-8";
  25.  
  26.    protected static XMLInputFactory xmlInFactory;
  27.    protected static XMLOutputFactory xmlOutFactory;
  28.  
  29.    static {
  30.       System.setProperty("javax.xml.stream.XMLInputFactory", "com.ctc.wstx.stax.WstxInputFactory");
  31.       System.setProperty("javax.xml.stream.XMLOutputFactory", "com.ctc.wstx.stax.WstxOutputFactory");
  32.       System.setProperty("javax.xml.stream.XMLEventFactory", "com.ctc.wstx.stax.WstxEventFactory");
  33.  
  34.       xmlInFactory = XMLInputFactory2.newInstance();
  35.       xmlOutFactory = XMLOutputFactory2.newInstance();
  36.    }
  37.    private XMLStreamReader getXMLStream(InputStream xml) throws XMLStreamException {
  38.  
  39.       return xmlInFactory.createXMLStreamReader(xml, ENCODING);
  40.  
  41.    }
  42.  
  43.    public long parseBatchDocument(InputStream xml) throws Exception {
  44.  
  45.       long counter = -1;
  46.       XMLStreamReader xmlReader = getXMLStream(xml);
  47.  
  48.       // Namespaces at the elements 'above'  the <my-ns:xml-message>
  49.       Map<string, String> globalNamespaces = new HashMap<string, String>();
  50.  
  51.       try {
  52.          while (xmlReader.hasNext()) {
  53.             switch (xmlReader.getEventType()) {
  54.                case XMLStreamConstants.START_DOCUMENT:
  55.                   System.out.println("Document started");
  56.                   break;
  57.                case XMLStreamConstants.START_ELEMENT:
  58.  
  59.                   if (MSG_TAG.equals(xmlReader.getName())) {
  60.                      // Start of a 'small' xml-message.
  61.                      String xmlMsg = extractMessage(xmlReader, globalNamespaces);
  62.                      handleMessage(xmlMsg);
  63.                      counter++;
  64.                   } else {
  65.                      // Some high-level tag containing more tags detected.
  66.                      // Get the namespaces at the highest level.
  67.                      // After that, we need to add these namespaces at lower level,
  68.                      // for every xml-message
  69.                      int nrOfNamespaces = xmlReader.getNamespaceCount();
  70.                      for (int i = 0; i <nrOfNamespaces; i++) {
  71.                         globalNamespaces.put(xmlReader.getNamespacePrefix(i), xmlReader.getNamespaceURI(i));
  72.                      }
  73.                   }
  74.                   break;
  75.                case XMLStreamConstants.END_DOCUMENT:
  76.                   System.out.println("Document ended");
  77.                   break;
  78.                default:
  79.                   // LOG.warn("unimplemented event type: " + xmlReader.getEventType());
  80.             }
  81.             // move to next event
  82.             if (xmlReader.hasNext()) {
  83.                xmlReader.next();
  84.             }
  85.          }
  86.       } catch (XMLStreamException e) {
  87.          throw new Exception(e);
  88.       }
  89.       return counter;
  90.  
  91.    }
  92.  
  93.  
  94.  
  95.    /**
  96.     * Copies all xml after the start element of 'xml-message' until the end element of 'xml-message' .
  97.     * @param xmlReader the batch xml
  98.     * @param namespaces the namespaces defined at high level
  99.     * @return the xml-message
  100.     * @throws Exception if any exception occurs
  101.     */
  102.    private String extractMessage(XMLStreamReader xmlReader, Map<string, String> namespaces)
  103.          throws Exception {
  104.       // Untill we reach the end tag we write everything to a buffer that will
  105.       // contain the xml-message content.
  106.       StringWriter sw = new StringWriter();
  107.       XMLStreamWriter xmlMsgWriter = null;
  108.  
  109.       try {
  110.  
  111.          xmlMsgWriter = xmlOutFactory.createXMLStreamWriter(sw);
  112.  
  113.          // Write first element with (global) namespaces
  114.          xmlMsgWriter.writeStartElement(xmlReader.getPrefix(), xmlReader.getLocalName(), xmlReader
  115.                .getNamespaceURI());
  116.          // Add all namespaces at global level (if any) to the new root element
  117.          Iterator keys = namespaces.keySet().iterator();
  118.          while (keys.hasNext()) {
  119.             String nsPrefix = (String) keys.next();
  120.             xmlMsgWriter.writeNamespace(nsPrefix, namespaces.get(nsPrefix));
  121.          }
  122.          // Get the attributes for the current element
  123.          copyAttributes(xmlReader, xmlMsgWriter);
  124.  
  125.  
  126.          // Now contiue with the loop
  127.          xmlReader.next();
  128.  
  129.          localLoop: while (xmlReader.hasNext()) {
  130.  
  131.             switch (xmlReader.getEventType()) {
  132.                case XMLStreamConstants.ATTRIBUTE:
  133.                   copyAttributes(xmlReader, xmlMsgWriter);
  134.                   break;
  135.                case XMLStreamConstants.CDATA:
  136.                   xmlMsgWriter.writeCData(xmlReader.getText());
  137.                   break;
  138.                case XMLStreamConstants.CHARACTERS:
  139.                   xmlMsgWriter.writeCharacters(xmlReader.getText());
  140.                   break;
  141.                case XMLStreamConstants.COMMENT:
  142.                   xmlMsgWriter.writeComment(xmlReader.getText());
  143.                   break;
  144.                case XMLStreamConstants.DTD:
  145.                   xmlMsgWriter.writeDTD(xmlReader.getText());
  146.                   break;
  147.                case XMLStreamConstants.NAMESPACE:
  148.                   copyNamespaces(xmlReader, xmlMsgWriter);
  149.                   break;
  150.                case XMLStreamConstants.START_ELEMENT:
  151.                   // Copy the start element
  152.                   xmlMsgWriter.writeStartElement(xmlReader.getPrefix(), xmlReader.getLocalName(), xmlReader
  153.                         .getNamespaceURI());
  154.                   // Add all attributes for this element
  155.                   copyAttributes(xmlReader, xmlMsgWriter);
  156.                   // Add all namespaces for this element
  157.                   copyNamespaces(xmlReader, xmlMsgWriter);
  158.                   break;
  159.                case XMLStreamConstants.END_ELEMENT:
  160.                   xmlMsgWriter.writeEndElement();
  161.                   if (MSG_TAG.equals(xmlReader.getName())) {
  162.                      break localLoop;
  163.                   }
  164.                case XMLStreamConstants.SPACE:
  165.                   // ignore spaces
  166.                   break;
  167.                default:
  168.                   System.out.println("Unknown eventType = " + xmlReader.getEventType());
  169.             }
  170.             // move to next event
  171.             if (xmlReader.hasNext()) {
  172.                xmlReader.next();
  173.             }
  174.  
  175.          } // end localLoop
  176.  
  177.          xmlMsgWriter.flush();
  178.       } catch (XMLStreamException e) {
  179.          throw new Exception(e);
  180.       } finally {
  181.  
  182.             if (xmlMsgWriter != null) {
  183.                xmlMsgWriter.close();
  184.             }
  185.             if (sw != null) {
  186.                sw.close();
  187.             }
  188.  
  189.       }
  190.       return sw.toString();
  191.    }
  192.  
  193.    /**
  194.     * Copies all attributes found at the current position in the xmlReader to the current
  195.     * position in the xmlWriter.
  196.     * @param xmlReader XMLStreamReader
  197.     * @param xmlWriter XMLStreamWriter
  198.     * @throws XMLStreamException if any xmlStream related exception occurs
  199.     */
  200.    private void copyAttributes(XMLStreamReader xmlReader, XMLStreamWriter xmlWriter) throws XMLStreamException {
  201.       int numOfAttr = xmlReader.getAttributeCount();
  202.       for (int i = 0; i <numOfAttr; i++) {
  203.          xmlWriter.writeAttribute(xmlReader.getAttributePrefix(i), xmlReader.getAttributeNamespace(i),
  204.                xmlReader.getAttributeLocalName(i), xmlReader.getAttributeValue(i));
  205.       }
  206.    }
  207.    /**
  208.     * Copies all namespaces found at the current position in the xmlReader to the current
  209.     * position in the xmlWriter.
  210.     * @param xmlReader XMLStreamReader
  211.     * @param xmlWriter XMLStreamWriter
  212.     * @throws XMLStreamException if any xmlStream related exception occurs
  213.     */
  214.    private void copyNamespaces(XMLStreamReader xmlReader, XMLStreamWriter xmlWriter) throws XMLStreamException {
  215.       int nrOfNamespaces = xmlReader.getNamespaceCount();
  216.       for (int i = 0; i <nrOfNamespaces; i++) {
  217.  
  218.          xmlWriter.writeNamespace(xmlReader.getNamespacePrefix(i), xmlReader.getNamespaceURI(i));
  219.       }
  220.    }
  221.  
  222.    private void handleMessage(String xml) {
  223.       System.out.println("====================================================");
  224.       System.out.println(xml);
  225.  System.out.println("+++++++++++++++++++++++++++++++++++++++++++++++++++");
  226.    }
  227. }

To have this class running you will need the following libraries: stax-api-1.0.1.jar and wstx-asl-3.1.1.jar.
Have fun with it!