[erledigt] Gumbo Parser: einen Iterator bauen



  • Hallo,

    Ich möchte mit dem Gumbo HTML Parser einen Iterator bauen. Die einzige Möglichkeit die mir einfällt das zu implementieren ist es, eine rekursive Routine zu einer iterativen Routine zu konvertieren. Dazu brauche ich wohl einen Stack wo ich die Elternelemente rein pushe, und sobald deren Kinder durchiteriert wurden ich zum Schwesternelement gehe und wieder das Gleiche machen.

    Jetzt weiß ich aber nicht genau wie ich die Bedingungen im operator++ genau stellen soll wann was gemacht werden soll. Deshalb poste ich mein aktueller Stand der Methode da mir hier vielleicht einer helfen kann. Ich versuche den Inhalt von example.net zu parsen, klappt auch bis zum body Tag aber das nächste Element im body Tag wird nicht mehr geparst.

    class html_parser{
    public:
        class iterator{
        public:
            iterator()
                : node{nullptr} {}
    
            iterator(GumboNode* p)
                : node{p} {}
    
            iterator& operator++(){
                bool popped{false};
    
                while(levels.size() && index() == node->parent->v.element.children.length - 1){
                    node = levels.top();
                    levels.pop();
                    popped = true;
                }
    
                iterator parent{node->parent};
    
                if(!popped && type() == GUMBO_NODE_ELEMENT && count() > 0){
                    levels.push(node);
                    node = child(0);
                }
    
                else if(index() < parent.count() - 1)
                    node = parent.child(index() + 1);
    
                return *this;
            }
    ...
    

    Brauche dringend etwas Nachhilfe.



  • Ohne den Rest der Klasse und Kommentare was die ganzen Steps deiner Meinung nach machen sollen ist der Code quasi unlesbar.



  • Schau dir mal Traversing Trees with Iterators an.
    Es gibt ja wohl schon jeweils den Parent-Node, dann sollte es damit möglich sein, komplett durchzuiterieren.



  • Ich glaube ich habs geschafft.

    Der Text von example.net wird nun erfolgreich durchiteriert, muss das Ganze aber noch ausgiebiger testen.

    Hier der aktuelle Code mit ein paar Kommentaren dazu:

            iterator& operator++(){
                // wenn die Node Kinder hat gehe zum ersten Kind
                if((node->type == GUMBO_NODE_ELEMENT || node->type == GUMBO_NODE_TEMPLATE) && node->v.element.children.length > 0)
                    node = (GumboNode*)node->v.element.children.data[0];
    
                // andernfalls wenn noch ein Kind folgt, auf dieses zeigen
                else if(node->index_within_parent < node->parent->v.element.children.length - 1)
                    node = (GumboNode*)node->parent->v.element.children.data[node->index_within_parent + 1];
    
                // ansonsten wieder mindestens eine Stufe tiefer das nächste Kind ermitteln
                else{
                    do{
                        node = node->parent;
                    } while(node && node->parent && node->index_within_parent == node->parent->v.element.children.length - 1);
    
                    if(node && node->parent)
                        node = (GumboNode*)node->parent->v.element.children.data[node->index_within_parent + 1];
                }
    
                return *this;
            }
    

Anmelden zum Antworten