The last time I had to interact with Java’s DOM API I noticed that it had not been updated to make use of any recent Java 5 enhancements. Specifically, the org.w3c.dom.NodeList interface does not implement java.lang.Iterable. The unfortunate side effect is ugly and error prone code.
// iteration sadness :( final NodeList nodes = document.getChildNodes(); for(int i = 0; i < nodes.getLength(); i++) { final Node node = nodes.item(i); // use node }
Ideally, the code could have been written utilizing Java 5′s foreach loop.
// iteration happiness which is currently impossible for(final Node node : document.getChildNodes()) { // use node }
As a workaround, I’ve written a simple wrapper class for org.w3c.dom.NodeList that makes it iterable. Hopefully, it’s useful for others.
Download: IterableNodeList.java
package com.trevorpounds.dom.util; import java.util.Iterator; import java.util.NoSuchElementException; import org.w3c.dom.Node; import org.w3c.dom.NodeList; /** * Simple org.w3c.dom.NodeList iterable wrapper * that can be used with Java's foreach loop. * * @author Trevor Pounds */ public class IterableNodeList implements Iterable<Node>, Iterator<Node> { /** List of nodes */ private final NodeList nodeList; /** List of nodes current index. */ private int index = 0; /** Constructs iterable node list. */ public IterableNodeList(final NodeList nodeList) { this.nodeList = nodeList; } /** {@inheritDoc} */ public boolean hasNext() { return index < nodeList.getLength(); } /** {@inheritDoc} */ public Iterator<Node> iterator() { return this; } /** {@inheritDoc} */ public Node next() throws NoSuchElementException { if(!hasNext()) { throw new NoSuchElementException(); } return nodeList.item(index++); } /** {@inheritDoc} */ public void remove() throws IllegalStateException, UnsupportedOperationException { throw new UnsupportedOperationException(); } }
Utilizing the wrapper class we can rewrite the sad code above to the following.
for(final Node node : new IterableNodeList(document.getChildNodes())) { // use node }
Perfect, thanks. Pity there isn’t an apache commons library for w3c dom (afaik), getting the feeling I’m re-inventing the wheel from time to time.
@Nico: It is definitely disheartening that many collection-type objects have not been updated to take advantage of this. I guess this is the best we can do.