如果当前DOM元素在迭代NodeList(通过getElementsByTagName()和其他元素创建)时被删除(通过JavaScript),元素将从NodeList中消失。这使得NodeList的正确迭代更加棘手。
public class IteratableNodeList implements Iterable<Node> {
final NodeList nodeList;
public IteratableNodeList(final NodeList _nodeList) {
nodeList = _nodeList;
}
@Override
public Iterator<Node> iterator() {
return new Iterator<Node>() {
private int index = -1;
private Node lastNode = null;
private boolean isCurrentReplaced() {
return lastNode != null && index < nodeList.getLength() &&
lastNode != nodeList.item(index);
}
@Override
public boolean hasNext() {
return index + 1 < nodeList.getLength() || isCurrentReplaced();
}
@Override
public Node next() {
if (hasNext()) {
if (isCurrentReplaced()) {
// It got removed by a change in the DOM.
lastNode = nodeList.item(index);
} else {
lastNode = nodeList.item(++index);
}
return lastNode;
} else {
throw new NoSuchElementException();
}
}
@Override
public void remove() {
throw new UnsupportedOperationException();
}
};
}
public Stream<Node> stream() {
Spliterator<Node> spliterator =
Spliterators.spliterator(iterator(), nodeList.getLength(), 0);
return StreamSupport.stream(spliterator, false);
}
}
然后使用它是这样的: new IteratableNodeList(doc.getElementsByTagName(elementType)). stream().filter(...)
或者: new IteratableNodeList(doc.getElementsByTagName(elementType)).forEach(...)
您不能对NodeList使用foreach循环,因为它没有实现Iterable接口。只有选项,您可以使用nodeList.getLength使用for或while循环。 http://docs.oracle.com/javase/7/docs/api/org/w3c/dom/NodeList.html –
虽然这是与你问的问题相切,但我会避开使用w3c来自Java标准库的东西。国际海事组织这是一个热门的混乱,有更好的XML解析库在那里。 – Jazzepi
+ Jazzepi我知道这是一个老话题,但是您建议使用哪种XML解析库?注意这个w3c库没有提供一个简单而通用的迭代器的事实是一个“细节”,但看起来像是针对这个东西的多一个参数(即使选择一个库可能比这个更复杂)。 –