首页 > 解决方案 > RemoveChild 删除第一个同名的孩子,但跳过下一个同名的孩子

问题描述

我有这个节点

<Record status="updated">
    <ID_Country>5</ID_Country>
    <ID_Currency>162</ID_Currency>
    <IsoCodeNumber>16  </IsoCodeNumber>
    <IsoCodeLetter version="old">AS  </IsoCodeLetter>
    <IsoCodeLetter version="new">ASAS  </IsoCodeLetter>
    <PostCode>    </PostCode>
    <CountryName>American Samoa  </CountryName>                        
    <isEuCountry>0</isEuCountry>
</Record>

我正在尝试将此节点添加到另一个 XML 文件中并看起来像这样。

<Record>
     <ID_Country>5</ID_Country>
     <ID_Currency>162</ID_Currency>
     <IsoCodeNumber>16  </IsoCodeNumber>         
     <IsoCodeLetter>ASAS  </IsoCodeLetter>
     <PostCode>    </PostCode>
     <CountryName>American Samoa  </CountryName>                        
     <isEuCountry>0</isEuCountry>
</Record>

这是我使用的代码

Node updatedNode = diffNode.cloneNode(true);
((Element) updatedNode).removeAttribute("status");    

for (int i = 0; i < updatedNode.getChildNodes().getLength(); i++)
{
    if (updatedNode.getChildNodes().item(i).getNodeType() == Node.ELEMENT_NODE)
    {                           
         Element e = (Element)updatedNode.getChildNodes().item(i);
         String string = e.getNodeName();

         if (e.hasAttribute("version") && e.getAttribute("version").equals("old"))
         {                 
              ((Element) updatedNode).removeChild((Node)e);                                
         }
         if(e.hasAttribute("version") && e.getAttribute("version").equals("new"))
         {              
               e.removeAttribute("version");
         }
    }
} 
productXML.adoptNode(updatedNode);
prodRoot.insertBefore(updatedNode, nextNode);

由于某种原因,当循环通过第一个 IsoCodeLetter 节点并将其删除时,它会跳过下一个并转到 PostCode,但第二个 IsoCodeLetter 仍在新节点中,我将其附加到 XML 文件中,看起来像这样。

<Record>
      <ID_Country>5</ID_Country>
      <ID_Currency>162</ID_Currency>
      <IsoCodeNumber>16  </IsoCodeNumber>         
      <IsoCodeLetter version="new">ASAS  </IsoCodeLetter>
      <PostCode>    </PostCode>
      <CountryName>American Samoa  </CountryName>                        
      <isEuCountry>0</isEuCountry>
</Record>

你有什么想法为什么会发生这种情况以及如何解决它?我正在使用 DOMParser 编写 XML 文件。

标签: javaxmlremovechildclonenode

解决方案


通过从元素中删除一个子元素,您将它从子节点中删除,这意味着下一个子元素现在位于您删除的子元素的索引处。但是你的循环继续下一个索引,跳过那个孩子。例如:假设您有:

0:孩子 A
1:孩子 B
2:孩子 C
3:儿童 D

对于i == 0,假设您不删除 Child A。您的循环将 1 添加到i,然后继续i == 1。您确实删除了 Child B。现在您有:

0:孩子 A
1:儿童 C
2:儿童 D

..但是您的循环i现在添加了一个,而i == 2您看到的下一个孩子是孩子 D。您从未看过孩子 C。

通常的解决方案是:

  1. 向后循环,因此索引正在减少,因此是否删除给定索引处的子级无关紧要;或者

  2. 在修改元素之前拍摄子节点列表的快照,这样当您从元素中删除子节点时,它不会从快照中删除

倒退是一个很容易的改变:

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

旁注:我可能也getChildNodes只调用一次并重用生成的NodeList对象:

NodeList children = updatedNode.getChildNodes();
for (int i = children.getLength() - 1; i >= 0; i--)
    // ...and use `children`, not `updatedNode.getChildNodes()`, in the loop body...
}

推荐阅读