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.
Обычные решения:
Цикл в обратном направлении, так что индекс уменьшается, и поэтому не имеет значения, удаляете ли вы дочерний элемент с данным индексом; или же
Сделайте снимок списка дочерних узлов перед изменением элемента, чтобы при удалении дочернего элемента из элемента он не удалялся из вашего снимка
Возвращение назад - довольно легкое изменение:
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...
}