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;
}
基本的に、すべての要素を反復処理するには2つの方法があります。
1。再帰の使用(私が考える最も一般的な方法):
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()
メソッドを使用:
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++)
より効率的にするために。
Javannaの答えの2番目の方法は、よりフラットで予測可能なメモリモデルを使用する傾向があるため、最適な場合があります。
私も最近この問題に出会いました。これが私の解決策です。再帰を避けたかったので、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;
}