Java Question

Java jdom2 - recursively parse XML

Im trying to make a recursive method that can parse / travel through an XML document using jdom2 in an XML with the following format

<rootElement>
<result>
<rowset>
<row>
<something>
<rowset>
<row>
<row> <--- I get to here. NullPointerException
<rowset>
<row>
<rowset>
<row>
<something>
<rowset>
<row>
<row>
<rowset>
<row>


Code

diTest(document.getRootElement().getChildren().iterator(), 7);
private static Iterator<Element> diTest(Iterator<Element> list, Integer count) {
// temp statement to avoid infinity loop.
if (count == 0) {
System.out.println("exited program");
System.exit(0);
}

// Test to keep track of count in output.
System.out.println("count is: " + count);

Element element = null;

while (list.hasNext()) {
element = list.next();

System.out.println(element.getName());
if (element.hasAttributes()) {
System.out.println(element.getAttributes());
}

if (element.getChildren().size() > 0) {
System.out.println(element.getAttributes());
System.out.println("");
break;
}
}

return diTest(element.getChildren().iterator(), count -1); //null pointer exception when it can't get more children on the last element... Need to go back somehow...
}// recursive end


When the method throws the nullpointerexception i believe its because its trying to get the children from a element that has none.

Question: How can i get past this problem, and make the method aware that it needs to step "back" up a level an onto the next element if it finds the "end of the road" to make sure that it is in fact the "end of the road"?

Any and all advice on this is very welcome, since i find it sketchy to find decent information on how to do this. Either i come across what to me is out of my level or so simple that i cant apply it to the problem i am trying to solve.

Example: 4*3*2*1 (recursive)

Edit



Thanks to the input from @Michael Kay i got my recursive method to read the entire XML document.

Sharing new method

private static void diReadXmlRecursively(Iterator<Element> list) {
Element element = null;

while (list.hasNext()) {
element = list.next();

System.out.println("Element name: " + element.getName());

diReadXmlRecursively(element.getChildren().iterator());
}
}

Answer

Consider the case where list is an empty iterator. Your code is:

Element element = null;
while (list.hasNext()) {
    element = list.next();
    ....
}
return diTest(element.getChildren()...)

If the first call on list.hasNext() returns false, then the assignment to element will not take place, therefore the call on element.getChildren() will throw an NPE.

You can also see that the logic is wrong because the body of the method always calls itself - if it weren't for the NPE, the recursion would therefore be infinite.

You can also see that the logic is wrong because you only call getChildren() on the last element child, whereas you presumably want to recurse for every element child.

The fix is simple: move the recursive call inside the loop:

while (list.hasNext()) {
    Element element = list.next();
    ....
    return diTest(element.getChildren()...)
}

There are a few other peculiar things about your code. The count variable is unnecessary. The "break" out of the loop if an element has children makes no sense. Displaying the attributes of an element only if it has children makes no sense.

Why is the method returning an iterator, and what do you expect this iterator to contain? I would expect your method to return nothing (void).

And it's not strictly wrong, but my instinct would be to pass the list on the recursive call, rather than an iterator over the list. That's because a list is generally more useful, e.g. you can count the number of items in the list if you want.

Comments