2

I have looked at the discussion in the link below - Merging xml file using java NodeList

I just need to use the same functionality using SAX parser, because I need to merge only two files but they are very big on size.

Please help on this.

File 1

<root>
    <Item>
        <a>jhiuo55jhj</a>
        <b>jhjoiohj</b>
        <c>jhjh334j</c>
    </Item>
</root>

File 2

<root>
    <Item>
        <x>jhi99jhj</x>
        <y>jhyty66jhj</y>
        <z>jhxdx3jhj</z>
    </Item>
</root>

Expected output

<root>
    <Item>
        <a>jhiuo55jhj</a>
        <b>jhjoiohj</b>
        <c>jhjh334j</c>
        <x>jhi99jhj</x>
        <y>jhyty66jhj</y>
        <z>jhxdx3jhj</z>
    </Item>
</root> 
1
  • Hi Adam, yes this is the requirement. Please help on this. Commented Feb 6, 2015 at 6:58

2 Answers 2

1

Basic solution, not including namespacing or attributes

  • Uses XMLStreamWriter to sink content from handler into one output
  • Skips over root elements so we don't put them in output twice

Code

public class XmlMerger {

    public static void main(String[] args) throws Exception {
        FileOutputStream outputStream = new FileOutputStream("output.xml");
        XMLStreamWriter out = XMLOutputFactory.newInstance().createXMLStreamWriter(new OutputStreamWriter(outputStream));

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

        Handler handler = new Handler(out);
        out.writeStartDocument();
        out.writeStartElement("root");
        saxParser.parse(new File("input1.xml"), handler);
        saxParser.parse(new File("input2.xml"), handler);
        out.writeEndElement();
        out.close();
    }

    private static class Handler extends DefaultHandler {

        private XMLStreamWriter out;
        private boolean dumping;

        public Handler(XMLStreamWriter out) {
            this.out = out;
        }

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

            if ("root".equals(qName)) {
                dumping = true;
            } else {
                try {
                    out.writeStartElement(qName);
                    // TODO attributes if you need them...
                } catch (XMLStreamException e) {
                    e.printStackTrace();
                }
            }
        }

        @Override
        public void endElement(String uri, String localName, String qName) throws SAXException {
            if ("root".equals(qName)) {
                dumping = false;
            } else {
                try {
                    out.writeEndElement();
                } catch (XMLStreamException e) {
                    e.printStackTrace();
                }
            }
        }

        @Override
        public void characters(char ch[], int start, int length) throws SAXException {
            if (!dumping) {
                return;
            }
            try {
                out.writeCharacters(ch, start, length);
            } catch (XMLStreamException e) {
                e.printStackTrace();
            }
        }

    }
}
Sign up to request clarification or add additional context in comments.

3 Comments

Thanks Adam, for your quick help. let me try this one, but I am getting error in the method endElement it is unable to resolve dumping and out these two.
@Adam, your program gives output like below, which is not what Sugata is asking for... <root> <Item> <a>jhiuo55jhj</a> <b>jhjoiohj</b> <c>jhjh334j</c> </Item> <Item> <x>jhi99jhj</x> <y>jhyty66jhj</y> <z>jhxdx3jhj</z> </Item> </root>
Hi Adam, I ran the code but it is appending two xmls, I need to merge each item from file1 with each Item of file 2. i.e final output will have all Items node containing all the fields of item node from file1 and file2.
0

I would say you to go for SAX-DOM approach here to get better performance.

Lets say below are the input xml files

1) First.xml
<root>
    <Item>
        <a>1</a>
        <b>2</b>
        <c>3</c>
    </Item>
    <Item>
        <a>1</a>
        <b>2</b>
        <c>3</c>
    </Item>
</root>
2) Second.xml
<root>
    <Item>
        <x>11</x>
        <y>22</y>
        <z>33</z>
    </Item>
    <Item>
        <x>44</x>
        <y>55</y>
        <z>66</z>
    </Item>
</root>

Steps for merging these xmls:

  1. Read the First.xml using DOM
  2. Now start reading the Second.xml using SAX
  3. Keep a counter variable i
  4. Whenever SAX parser finds startElement for Item node, fetch the other fields from First.xml of ith Item node, which is stored in DOM.
  5. i++
  6. Write the content to OutputStream
  7. Parsing done, close Outputstream

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.