Удалить дочерние узлы из родительского - PugiXML

<Node>
  <A>
    <B id = "it_DEN"></B>
  </A>
  <A>
    <B id = "en_KEN"></B>
  </A>
  <A>
    <B id = "it_BEN"></B>
  </A>
</Node>

Как я могу удалить дочерний узел <A></A>, у которого есть дочерний узел <B></B>, атрибут id которого не начинается с it с помощью PugiXML. Результат будет следующим:

<Node>
  <A>
    <B id = "it_DEN"></B>
  </A>
  <A>
    <B id = "it_BEN"></B>
  </A>
</Node>

person vincent911001    schedule 25.05.2016    source источник
comment
Так что ты думаешь? Какой способ вы придумали?   -  person Chanhee Jo    schedule 25.05.2016
comment
Я пытаюсь использовать Xpath для поиска дочерних узлов, которые мне не нужны, а затем удалить их из родительского узла, но, похоже, API не имеет такой функциональности. Итак, я думаю, я бы попытался удалить все это, а затем добавить необходимые дочерние узлы обратно, если нет другой альтернативы.   -  person vincent911001    schedule 25.05.2016


Ответы (2)


Это немного сложно, если вы хотите удалить узлы во время итерации (чтобы код оставался однопроходным). Вот один из способов сделать это:

bool should_remove(pugi::xml_node node)
{
    const char* id = node.child("B").attribute("id").value();
    return strncmp(id, "it_", 3) != 0;
}

for (pugi::xml_node child = doc.child("Node").first_child(); child; )
{
    pugi::xml_node next = child.next_sibling();

    if (should_remove(child))
        child.parent().remove_child(child);

    child = next;
}

В качестве альтернативы вы можете просто использовать XPath и удалить результаты:

pugi::xpath_node_set ns = doc.select_nodes("/Node/A[B[not(starts-with(@id, 'it_'))]]");

for (auto& n: ns)
    n.node().parent().remove_child(n.node());
person zeuxcg    schedule 25.05.2016
comment
Привет, большое спасибо за вашу помощь, да, мне просто интересно, есть ли способ сделать это с помощью xpath, большое спасибо. - person vincent911001; 25.05.2016

Другой способ — увеличить итератор перед удалением потомка. Чтобы удалить атрибут во время итерации.

for(pugi::xml_attribute_iterator it = node.attributes_begin(); it != node.attributes_end();){
    pugi::xml_attribute attr = *it++;
    if(should_remove(attr)){
        node.remove_attribute(attr);
    }
}
person Neel Basu    schedule 30.05.2020