Search code examples
javaxmlxpathsax

Split XML using SAX parser


I have following xml file.

<Engineers>
    <Engineer>
        <Name>JOHN</Name>
        <Position>STL</Position>
        <Team>SS</Team>
    </Engineer>
    <Engineer>
        <Name>UDAY</Name>
        <Position>TL</Position>
        <Team>SG</Team>
    </Engineer>
    <Engineer>
        <Name>INDRA</Name>
        <Position>Director</Position>
        <Team>PP</Team>
    </Engineer>
</Engineers>

I need to split this xml into smaller xml strings when Xpath is given as Engineers/Enginner.

Smaller xml strings are as follows

<Engineers>
    <Engineer>
        <Name>INDRA</Name>
        <Position>Director</Position>
        <Team>PP</Team>
    </Engineer>
</Engineers>

<Engineers>
    <Engineer>
        <Name>JOHN</Name>
        <Position>STL</Position>
        <Team>SS</Team>
    </Engineer>
</Engineers>

I have implemented following so far using SAX which we can get the elements inside XML but not as what I want.How can I proceed??

public class ReadSAX
{
    public static void main( String[] args )
    {
        try {

              SAXParserFactory factory = SAXParserFactory.newInstance();
              SAXParser saxParser = factory.newSAXParser();

              DefaultHandler handler = new DefaultHandler() {

   public void startElement(String uri, String localName,
                    String qName, Attributes attributes)
                    throws SAXException {

                  System.out.println("Start Element :" + qName);



                public void endElement(String uri, String localName,
                        String qName)
                        throws SAXException {

                      System.out.println("End Element :" + qName);

                }

                public void characters(char ch[], int start, int length)
                    throws SAXException {

                  System.out.println(new String(ch, start, length));


                 }

              };

              File file = new File("c:\\file.xml");
              InputStream inputStream= new FileInputStream(file);
              Reader reader = new InputStreamReader(inputStream,"UTF-8");

              InputSource is = new InputSource(reader);
              is.setEncoding("UTF-8");

              saxParser.parse(is, handler);


            } catch (Exception e) {
              e.printStackTrace();
            }

    }
}

Solution

  • Why use such a low-level coding approach?

    In XSLT 2.0 it's simply

    <xsl:template match="/">
      <xsl:for-each select="Engineers/Engineer">
        <xsl:result-document select="{position()}.xml">
          <Engineers>
            <xsl:copy-of select="."/>
          </Engineers>
        </xsl:result-document>
      </xsl:for-each>
    </xsl:template> 
    

    and if that takes too much memory, get a streaming XSLT 3.0 processor which will solve the problem.