removeChild()方法正在打破循环

时间:2014-02-06 14:54:33

标签: java xml java-ee jaxp

我正在使用以下代码从XMl文件中删除多个元素。

NodeList removeNodeList = doc.getElementsByTagName("server1");
Element rootElement = doc.getDocumentElement();

for (int i = 0; i < removeNodeList.getLength(); i++) {
    rootElement.removeChild(removeNodeList.item(i));
}

但是在删除一个元素之后它就会脱离循环。问题是什么。

以下是我的XML文件内容。

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<start>

    <category name="server1"/>
    <category name="server2"/>

    <server1 name="serverName1" value="serverValue"/>
    <server1 name="serverName1" value="serverValue"/>

    <server2 name="serverName2" value="serverValue"/>

</start>

4 个答案:

答案 0 :(得分:1)

我找到了解决方案:

让我详细解释一下这个问题。

NodeList removeNodeList = doc.getElementsByTagName("server1"); removeNodeList.getLength()将返回2,因为有2个节点具有nodeName server1,然后执行rootElement.removeChild(removeNodeList.item(i));,然后检查for loop条件i.e. i的值是1removeNodeList.getLength()返回1,因为现在server1中仅有1个nodeName为DOM document的节点,此条件失败为1 < 1 is false < / p>

所以我采用了以下方法:

一旦不再使用NodeList,就删除所有元素。

NodeList nodes = doc.getElementsByTagName(elementName);
Set<Element> targetElements = new HashSet<Element>();

for (int i = 0; i < nodes.getLength(); i++) {
    Element e = (Element)nodes.item(i);
    targetElements.add(e);
}
for (Element e: targetElements) {
    e.getParentNode().removeChild(e);
}

答案 1 :(得分:0)

从列表中删除元素会将其大小减1,这会破坏迭代。您需要按照此问题中的描述向后迭代列表(从最后一个节点到第一个节点):

Removing DOM nodes when traversing a NodeList

答案 2 :(得分:0)

如前所述,删除元素会减小列表的大小,但计数器仍在增加(i ++):

  var request = new Request(cacheKey, {credentials: 'include'});
  return fetch(request).then(function(response) {

我认为最简单的解决方案是在循环中删除i ++部分。

[element 1] <- Delete 
[element 2]
[element 3]
[element 4]
[element 5]

[element 2]  
[element 3] <- Delete
[element 4]
[element 5]
--

[element 2]  
[element 4] 
[element 5] <- Delete
--
--

[element 2]  
[element 4] 
--
--
--

指针停留在同一位置。 列表会自行移动。

for (int i = 0; i < removeNodeList.getLength();) {
    rootElement.removeChild(removeNodeList.item(i));
}

答案 3 :(得分:0)

要从xml文档中删除removeNodeList中包含的所有元素:

由于该节点也已从removeNodeList中删除,因此下一个要删除的节点位于removeNodeList中的索引0上,直到列表为空(removeNodeList.getLength() == 0

while(removeNodeList.getLength() > 0) {
    rootElement.removeChild(removeNodeList.item(0));
}

仅当每个节点"server1"是节点"start"的子节点时,此方法才有效。 如果xml将包含"server1"个节点作为不同于节点rootElement的节点的子节点(“启动”),则将抛出DOMException,因为要删除的节点不是rootElement的子节点。

例如:

<category name="server1"/>
<category name="server2"/>

<server1 name="serverName1" value="serverValue"/>
<other>
   <server1 name="serverName1" value="serverValue"/>
</other>

<server2 name="serverName2" value="serverValue"/>

要处理这种情况,请删除该项目的父节点:

while(removeNodeList.getLength() > 0) {
    Node itemToRemove = removeNodeList.item(0);
    itemToRemove.getParentNode().removeChild(itemToRemove);
}

要有条件地删除元素,例如基于某些属性值:

仅当方法shouldRemoveNode()返回true时,才会删除节点。 如果为false,则该节点保留在文档和removeNodeList中,(可能)要删除的下一个节点位于索引=当前索引+ 1
notRemovedCnt既是未删除的节点数,也是下一个要检查是否应删除的元素的索引, 只要removeNodeList的长度和notRemoveCnt相等,就意味着列表中没有要删除的元素。

int notRemovedCnt = 0;
while(removeNodeList.getLength() > notRemovedCnt) {
    Node itemToRemove = removeNodeList.item(notRemovedCnt);
    if (shouldRemoveNode(itemToRemove)) {
        itemToRemove.getParentNode().removeChild(itemToRemove); 
    } else {
        notRemovedCnt++;
    }
}