Kasowanie danego elementu xml w Qt

Odpowiedz Nowy wątek
2019-10-12 17:06

Rejestracja: 2 lata temu

Ostatnio: 9 godzin temu

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

Pozostało 580 znaków

2019-10-12 20:01

Rejestracja: 1 rok temu

Ostatnio: 1 tydzień temu

Lokalizacja: Yuri' Command Center

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.


Sole trader in Poland - "Codedemens Software"
Working on a game project I've named "Demented Shooters" (2D shooter, with sandbox properties, physics, GLSL shaders, and awesome multiplayer)

C++ Software Engineer, Game Developer, Graphic Designer (2d), Audio Implementer, Voice Actor, Enterprenuer,
edytowany 11x, ostatnio: Codedemens, 2019-10-12 20:38

Pozostało 580 znaków

2019-10-12 22:16

Rejestracja: 2 lata temu

Ostatnio: 9 godzin temu

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");

edytowany 1x, ostatnio: pestka12, 2019-10-12 22:20
No tak. Po co czytać wsystko to co napisalem, skoro można to pominąć, bo przecież rozwiązanie (a właściwie jego bezmyślne skopiowanie) jest najważniejsze (w sytuacji gdy nawet nie wiem co to jest za zmienna "nazwa" i jak algorytm faktycznie ma wyglądać z tak dziwną logiką tego algorytmu), a nie to, co Ci podałem jak rozwiązać ten problem samodzielnie. - Codedemens 2019-10-13 00:35
Sprawdź link na stackoverflow. Pare informacji dodatkowych się dowiesz. - Codedemens 2019-10-13 00:37

Pozostało 580 znaków

2019-10-12 22:50

Rejestracja: 5 miesięcy temu

Ostatnio: 5 miesięcy temu

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.

Pozostało 580 znaków

2019-10-13 14:31

Rejestracja: 2 lata temu

Ostatnio: 9 godzin temu

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.

Pozostało 580 znaków

Odpowiedz

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