Java:迭代org.w3c.dom.Document中所有元素的最有效方法?

在Java中遍历所有DOM元素的最有效方法是什么?

像这样的东西,但对于当前org.w3c.dom.Document每个DOM元素?

 for(Node childNode = node.getFirstChild(); childNode!=null;){ Node nextChild = childNode.getNextSibling(); // Do something with childNode, including move or delete... childNode = nextChild; } 

基本上你有两种方法遍历所有元素:

1.使用recursion (我认为最常见的方式):

 public static void main(String[] args) throws SAXException, IOException, ParserConfigurationException, TransformerException { DocumentBuilderFactory docBuilderFactory = DocumentBuilderFactory .newInstance(); DocumentBuilder docBuilder = docBuilderFactory.newDocumentBuilder(); Document document = docBuilder.parse(new File("document.xml")); doSomething(document.getDocumentElement()); } public static void doSomething(Node node) { // do something with the current node instead of System.out System.out.println(node.getNodeName()); NodeList nodeList = node.getChildNodes(); for (int i = 0; i < nodeList.getLength(); i++) { Node currentNode = nodeList.item(i); if (currentNode.getNodeType() == Node.ELEMENT_NODE) { //calls this method for all the children which is Element doSomething(currentNode); } } } 

2.避免使用带*作为参数的getElementsByTagName()方法进行recursion

 public static void main(String[] args) throws SAXException, IOException, ParserConfigurationException, TransformerException { DocumentBuilderFactory docBuilderFactory = DocumentBuilderFactory .newInstance(); DocumentBuilder docBuilder = docBuilderFactory.newDocumentBuilder(); Document document = docBuilder.parse(new File("document.xml")); NodeList nodeList = document.getElementsByTagName("*"); for (int i = 0; i < nodeList.getLength(); i++) { Node node = nodeList.item(i); if (node.getNodeType() == Node.ELEMENT_NODE) { // do something with the current element System.out.println(node.getNodeName()); } } } 

我认为这些方式都是有效的。
希望这可以帮助。

for (int i = 0; i < nodeList.getLength(); i++)

改成

for (int i = 0, len = nodeList.getLength(); i < len; i++)

更高效。 第二种方法可能是最好的,因为它倾向于使用更扁平,可预测的内存模型。

最近我也偶然发现了这个问题。 这是我的解决scheme。 我想避免recursion,所以我用了一个while循环。

由于添加和删除列表上的任意位置,我去了LinkedList实现。

 /* traverses tree starting with given node */ private static List<Node> traverse(Node n) { return traverse(Arrays.asList(n)); } /* traverses tree starting with given nodes */ private static List<Node> traverse(List<Node> nodes) { List<Node> open = new LinkedList<Node>(nodes); List<Node> visited = new LinkedList<Node>(); ListIterator<Node> it = open.listIterator(); while (it.hasNext() || it.hasPrevious()) { Node unvisited; if (it.hasNext()) unvisited = it.next(); else unvisited = it.previous(); it.remove(); List<Node> children = getChildren(unvisited); for (Node child : children) it.add(child); visited.add(unvisited); } return visited; } private static List<Node> getChildren(Node n) { List<Node> children = asList(n.getChildNodes()); Iterator<Node> it = children.iterator(); while (it.hasNext()) if (it.next().getNodeType() != Node.ELEMENT_NODE) it.remove(); return children; } private static List<Node> asList(NodeList nodes) { List<Node> list = new ArrayList<Node>(nodes.getLength()); for (int i = 0, l = nodes.getLength(); i < l; i++) list.add(nodes.item(i)); return list; }