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.

1 ответ

Решение

Удаляя дочерний элемент из элемента, вы удаляете его из дочерних узлов, что означает, что следующий дочерний элемент теперь находится в индексе дочернего элемента, который вы удалили. Но ваш цикл продолжается со следующего индекса, пропуская этого потомка. Например: предположим, у вас есть:

0: ребенок А
1: ребенок B
2: ребенок C
3: ребенок D

За i == 0 скажем, вы не удаляете Child A. Ваш цикл добавляет один к i и вы продолжаете с i == 1, Вы удалите Ребенка Б. Теперь у вас есть:

0: ребенок А
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...
}
Другие вопросы по тегам