Kasowanie danego elementu xml w Qt

0

Witam wszystkich
Mam pytanie bo ostatnio udało mi się rozwiązać problem z kasowaniem ale okazało się dzisiaj że kasuje tylko 1 element pliku xml a reszty nie kasuje chociaż mu wskazuje na to.
Kod Xml:

<Lista>
 <Baza sciezka="Test" name="Testname"/>
 <Baza sciezka="Test2" name="Testname2"/>
</Lista>

A oto kod C++:

document.setContent(&deletexml);
    lista=document.elementsByTagName("Lista");
    for(int i=0;i<lista.count();i++)
    {
       itemnode=lista.at(i);
       itemelement=itemnode.firstChildElement("Baza");
       if(!itemelement.isNull()&&itemelement.attribute("name")==nazwa)
       {
           itemnode.removeChild(itemelement);
       }

    }

Problem polega na tym że kasuje się tylko pierwsza linijka gdzie name="Testname"
A program ma kasować to na co mu wskażę.

Bardzo dziękuje za pomoc i życzę miłego dnia/wieczora

1

Nie do końca wiem, ale jeżeli masz warunek

itemelement.attribute("name")==nazwa

To w przypadku dwóch elementów o dwóch różnych nazwach (name=Testname, name=Testname2), skasuje tylko jeden element (poza tym, czym jest konkretnie zmienna "nazwa" w tym kodzie?)

Poza tym... nie wiem też czy ta cała pętla nie ma sensu w sytuacji, gdy usuwasz elementy z listy, która się kurczy,przy jednocześnym inkrementowaniem licznika i.

Nie znam biblioteki qt, ale tego typu pętla (gdzie inkrementujesz licznik za każdym razem jak kasujesz element) w typowym kontenerze std-owskim nie miała by absolutnie żadnego sensu.

Edit:
https://stackoverflow.com/questions/21721208/qdom-remove-nodes

Tutaj z tego co widzę człowiek chciał dokładnie zrobić to samo
Wyobraź sobie sytuację. Masz kontener z czterema elementami

{El1, El2, El3, El4}

W

lista[0] = El1, 
lista[1] = El2, 
lista[2] = El3, 
lista[3] = El4

Rozpoczynasz pętle, i = 0; i < lista.count() czyli 4; ++i

Usuwasz lista[0] (El1)
Lista wygląda teraz tak:
{El2, El3, El4}

Ale El2 to już nie jest lista[1], tylko lista[0], bo skasowałeś jeden element,

lista[0] = El2, 
lista[1] = El3, 
lista[2] = El4

I teraz licznik i zwiększasz o 1. Po skasowaniu elementu i przesunięciu elementów o jeden po prawej stronie od elementu skasowanego

I próbujesz skasować lista[1]. Chciałeś skasować kolejny element - El2, a nie El3, skasowałeś El3. Przeskoczyłeś o dwie pozycje.

Według mnie rozwiązanie mogłoby wygladać mniej więcej tak (zakładając, że te warunki które podaleś faktycznie takie mają być):

int i = 0;
while (i < lista.count()) {
    itemnode=lista.at(i);
    itemelement=itemnode.firstChildElement("Baza")
    if(!itemelement.isNull()&&itemelement.attribute("name")==nazwa)
    {
        itemnode.removeChild(itemelement);
    } else {
        ++i; 
    }
}

Kiedy kasujesz element - kasujesz element i nic z i nie robisz, bo prawa strona kontenera przejdzie w lewą strone
Kiedy nie kasujesz - przeskakujesz z licznikiem o jedną pozycje do przodu.

0

nazwa to typ QString która przetrzymuje nazwę czyli np:Testname.

A kod który napisałeś nic nie robi. W sensie nie kasuje żadnego elementu nawet pierwszego.

Dopiero kasuje pierwszy element jak lista=document.elementByTagName("Lista");

1

Jakoś dziwnie to robisz.
Tak jak pisał @Codedemens powinieneś aktualizować licznik po usunięciu elementu.
Krótka analiza Twojego kodu:

document.setContent(&deletexml);
    lista=document.elementsByTagName("Lista"); // pobieram wszystkie nody Lista z dokumentu
    for(int i=0;i<lista.count();i++) //iteruje po tych nodach (czyli po jednym głównym nodzie)
    {
       itemnode=lista.at(i); //wybieram noda (jest tylko jeden "Lista")
       itemelement=itemnode.firstChildElement("Baza"); //pobieram pierwszy element "Baza"
       if(!itemelement.isNull()&&itemelement.attribute("name")==nazwa)  // sprawdzam ... 
       {
           itemnode.removeChild(itemelement);
       }

    }

Jak widzisz nie ma to sensu.

To powinno działać dla Twojego przypadku:

    document.setContent(source);
    QDomNodeList ListaList = document.elementsByTagName("Lista");
    for(int j=0;j<ListaList.count();++j){
        QDomNode ListaListNode = ListaList.at(j);
        QDomNodeList ListaListNodeList = ListaListNode.childNodes();
        for(int i=0;i<ListaListNodeList.count();++i){
            QDomNode node=ListaListNodeList.at(i);
            QDomElement element = node.toElement();
            if(element.tagName() != "Baza")
                continue;
            if(!element.isNull() && element.attribute("name") == name){
                ListaListNode.removeChild(node);
                --i;
            }
        }
    }

Dla dokumentu

<something>
<Lista>
 <Baza sciezka="Test" name="Testname"/>
 <Baza sciezka="Test2" name="Testname2"/>
 <Baza1 sciezka="Test2" name="Testname"/>

 <Baza sciezka="Test3" name="Testname"/>
 <Baza sciezka="Test4" name="Testname4"/>
 <Baza sciezka="Test5" name="Testname"/>
...
</Lista>

<Lista>
 <Baza sciezka="Test" name="Testname"/>
 <Baza sciezka="Test3" name="Testname"/>
</Lista>

<Lista>
...
</something>

Jeśli Lista to Twój główny node, wtedy interesuje Cię tylko wewnętrzna część pętli.

1

Bardzo dziękuje za pomoc wszystkim.

@Wiechu Kod który napisałeś działa i śmiga. Kasuje taki element na który wskażę.

Naprawdę bardzo dziękuje wszystkim za pomoc i życzę miłego dnia/wieczora.

1 użytkowników online, w tym zalogowanych: 0, gości: 1