【问题标题】:JAVA XML remove Node - only first appearance is removedJAVA XML 删除节点 - 仅删除第一个外观
【发布时间】:2014-05-25 08:24:45
【问题描述】:

我有这种从 XML 文件中删除节点的方法:

public static void deleteElement(Document doc, String elementType, String tagName, String valueToCheck) {
        // <elementType>
        NodeList nodes = doc.getElementsByTagName(elementType);
        System.out.println("NODES: "+nodes.getLength());
        for (int i = 0; i < nodes.getLength(); i++) {
            Element person = (Element) nodes.item(i);
            // <tagName>
            Element name = (Element) person.getElementsByTagName(tagName).item(0);
            String pName = name.getTextContent();
            System.out.println(pName);
            if (pName.equals(valueToCheck)) {
                person.getParentNode().removeChild(person);
                System.out.println("match" + pName);
            }
        }
        System.out.println("NODES AFTER DELETE: "+nodes.getLength());
    }

这里我指定了根元素、要检查的标签和要检查的值。

在我的 XML 上:

<?xml version="1.0"?>
    <book>
      <person>
        <id>1</id>
        <name>Person 1</name>
      </person>
      <person>
        <id>1</id>
        <name>Person 2</name>
      </person>
      <person>
        <id>3</id>
        <name>Person 3</name>
      </person>
      <person>
        <id>4</id>
        <name>Person 3</name>
      </person>
    </book>

执行带有参数personnamePerson 3的方法后的输出是这样的:

<?xml version="1.0" encoding="UTF-8"?>
<book>
  <person>
    <id>1</id>
    <name>Person 1</name>
  </person>
  <person>
    <id>1</id>
    <name>Person 2</name>
  </person>
  <person>
    <id>4</id>
    <name>Person 3</name>
  </person>
</book>

即只删除了第一个外观...任何想法为什么?

【问题讨论】:

  • 在您的情况下 elementType 的值是多少?

标签: java xml dom xml-parsing


【解决方案1】:

DOM 节点列表是活动的,换句话说,当您修改文档时,节点列表会更改以反映文档的新状态。在循环的第三次迭代中,您从文档中删除了第一个匹配元素 (item(2))。这也导致它从nodes 列表中消失,将列表缩短一个节点并将其后的所有内容向上移动一个索引 - 第二个匹配节点变为item(2)。然后你增加i 并发现它是== nodes.getLength() 并且循环结束而不处理最后一个条目。

为避免这种情况,请向后迭代:

for (int i = nodes.getLength() - 1; i >= 0; i--)

【讨论】: