3

I have the following xml file:

<?xml version="1.0"?>
<CONFIG>
    <FUNCTION>
        <NAME>FUNCT0</NAME>
        <CALLS>
            <FUNCTION>
            <NAME>FUNCT0_0</NAME>
            </FUNCTION>
        </CALLS>
        <CALLS>
            <FUNCTION>
            <NAME>FUNCT0_1</NAME>
            </FUNCTION>
        </CALLS>
    </FUNCTION>
    <FUNCTION>
        <NAME>FUNCT1</NAME>
    </FUNCTION>
</CONFIG>

I have a class called FunctionInfo which stores both a function's name and also contains an ArrayList to contains the subfunctions which the function calls.

I want to end up with an ArrayList which contains the top-level functions that will then store their subfunctions inside the object recursively.

I need this to work for an indefinite depth of recursion.

My question is what is the easiest way to write a recursive XML parser that can perform this task?

Edit: I am working in Java.

Thanks :)

3
  • I'm assuming this is in Java based on your question? Commented Nov 8, 2012 at 18:45
  • Yes, sorry forgot to mention. Commented Nov 8, 2012 at 19:02
  • Read up on SAX event-driven parsing. Commented Nov 8, 2012 at 19:20

2 Answers 2

8

Unless your file is huge, you can use the java DOM parser (the DOM parser keeps the file in memory)

Given a node (starting with the root), you can enumerate its children, and then call the same function on each child recursively.

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

public class RecursiveDOM {
    public static void main(final String[] args) throws SAXException, IOException, ParserConfigurationException {
        new RecursiveDOM("file.xml");
    }

    public RecursiveDOM(final String file) throws SAXException, IOException, ParserConfigurationException {
        final DocumentBuilderFactory dbfac = DocumentBuilderFactory.newInstance();
        final DocumentBuilder docBuilder = dbfac.newDocumentBuilder();
        final Document doc = docBuilder.parse(this.getClass().getResourceAsStream(file));
        final List<String> l = new ArrayList<String>();
        parse(doc, l, doc.getDocumentElement());
        System.out.println(l);
    }

    private void parse(final Document doc, final List<String> list, final Element e) {
        final NodeList children = e.getChildNodes();
        for (int i = 0; i < children.getLength(); i++) {
            final Node n = children.item(i);
            if (n.getNodeType() == Node.ELEMENT_NODE) {
                list.add(n.getNodeName());
                parse(doc, list, (Element) n);
            }
        }
    }

}

Result:

[FUNCTION, NAME, CALLS, FUNCTION, NAME, CALLS, FUNCTION, NAME, FUNCTION, NAME]
Sign up to request clarification or add additional context in comments.

1 Comment

Cool thanks. I actually managed to do it myself. But thanks anyway.
1

Also, you can consider using JAXB (mapping classes to XML), which would result in a tree of java classes, if implemented properly each class can implement a particular type of function so the tree can be recursively "calculated".

This is a basic JAXB implementation, use Config.unmarshal to rebuild it from an InputStream:

import java.io.OutputStream;
import java.io.Reader;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;

public class TestJAXB {

    public static void main(final String[] args) throws JAXBException {
        final Function e5 = new Function("N5", null);
        final Function e6 = new Function("N6", null);
        final Function e4 = new Function("N4", null);
        final Function e2 = new Function("N2", ((new Call[] { new Call(e4) })));
        final Function e3 = new Function("N3", ((new Call[] { new Call(e5) })));
        final Function e1 = new Function("N1", ((new Call[] { new Call(e2), new Call(e3) })));
        new Config(new Function[] { e1, e6 }).marshall(System.out);
    }

    @XmlRootElement(name = "CONFIG")
    static class Config {
        @XmlElement(name = "FUNCTION")
        private Function[] functions;

        public Config(final Function[] f) {
            this.functions = f;
        }

        protected Config() {
        }

        public void marshall(final OutputStream out) throws JAXBException {
            final JAXBContext jaxbContext = JAXBContext.newInstance(this.getClass());
            final Marshaller marshaller = jaxbContext.createMarshaller();
            marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
            marshaller.marshal(this, out);
        }

        public final static Config unmarshall(final Reader r) throws JAXBException {
            final JAXBContext jaxbContext = JAXBContext.newInstance(Config.class);
            final Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
            return (Config) unmarshaller.unmarshal(r);
        }

    }

    @XmlRootElement(name = "FUNCTION")
    static class Function {
        @XmlElement(name = "NAME")
        String name;

        @XmlElement(name = "CALLS")
        Call[] calls;

        public Function(final String name, final Call[] calls) {
            this.name = name;
            this.calls = calls;
        }

        protected Function() {
        }

    }

    @XmlRootElement(name = "CALL")
    static class Call {
        @XmlElement(name = "FUNCTION")
        Function f;

        protected Call() {
        }

        public Call(final Function f) {
            this.f = f;
        }

    }
}

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.