Formular-Elemente aus einer HTML Seite extrahieren



  • Hi Alle zusammen!

    Ich test gerade an klein wenig mit der CppWebBrowser Compo herum und möchte nun aus einem HTML Formular alle Formularelemente und gewisse zugehörige Werte (Editfelder, Buttons usw.) in einer Liste anzeigen lassen.

    Dazu muss man ja irgendwie die IHTMLElementCollection des Formulars durchforsten. Nur habe ich leider keinen blassen Dunst wie ich das anstellen soll. pAll->item() liefert mir ja nur ein Element zurück, dessen Namen ich schon kenne. Ich will aber alle Elemente des Formulars haben und dann entsprechend in eine Liste eintragen.

    Hat jemand einen Vorschlag wie ich das am Besten anstellen kann?

    Mein Code bisher:

    void __fastcall TForm1::CppWebBrowser1DocumentComplete(TObject *Sender, LPDISPATCH pDisp, Variant *URL)
    {
         IHTMLDocument2 *HTMLDocument = NULL;
    
         if (SUCCEEDED(CppWebBrowser1->Document->QueryInterface(IID_IHTMLDocument2, (LPVOID*)&HTMLDocument)))
         {
            if (HTMLDocument != NULL)
            {
               IHTMLElementCollection *pAll = NULL;
    
               if (SUCCEEDED(HTMLDocument->get_all(&pAll)) && pAll)
               {
                  long iColLengh;
                  pAll->get_length(&iColLengh);
    
                  for (long i=0; i<iColLengh; i++)
                  {
                      TVariant vName;
                      TVariant vIndex = 0;
                      IDispatch *pDisp = NULL;
    
                      WideString wsECName;
    
                      pAll->toString(&wsECName);
    
                      if (SUCCEEDED(pAll->item(vName, vIndex, &pDisp)) && pDisp)
                      {
                         IHTMLInputElement *pInput = NULL;
    
                         // pInput bleibt NULL, da ich ja keinen Namen spezifiziert habe
                         if (SUCCEEDED(pDisp->QueryInterface(IID_IHTMLInputElement, (LPVOID*)&pInput)) && pInput)
                         {
                            // String des Elementes holen
                            WideString wsElementName;
                            pInput->get_name(&wsElementName);
                         }
    
                         pDisp->Release();
                      }
                  }
    
                  pAll->Release();
               }
            }
    
            HTMLDocument->Release();
         }
    }
    


  • Wenn ich die MDSN richtig verstehe dann kannst du vName auch eienn Integer zuweisen. Damit sollte es doch eigentlich möglich sein, quasi auf Verdacht durch die Collection zu iterieren. Sobald der Aufruf fehlschlägt sollte das Ende der Collection erreicht sein.



  • Jawohl! Ich habe mir mal auf Grund Deines Tipps 👍 das Beispiel in der MSDN angeschaut und hatte Erfolg.

    Der Schlüssel liegt in der Zeile

    if (SUCCEEDED(pAll->item(vIndex, vIndex, &pDisp)) && pDisp)
    

    begraben. Über die einfache Angabe des Indexes kann mann schön in der Element-Liste rumiterieren. Hier mal mein Beispielcode, der alle Input-Elemente (Name, Typ, Wert) einer bel. Webseite auflistet:

    void __fastcall TForm1::CppWebBrowser1DocumentComplete(TObject *Sender, LPDISPATCH pDisp, Variant *URL)
    {
         IHTMLDocument2 *HTMLDocument = NULL; // Zeiger auf das geladene Document
    
         TListItem *ListItem;
         lvElements->Items->Clear();
    
         // falls eine Seite geladen
         if (SUCCEEDED(CppWebBrowser1->Document->QueryInterface(IID_IHTMLDocument2, (LPVOID*)&HTMLDocument)))
         {
            if (HTMLDocument != NULL)
            {
               IHTMLElementCollection *pAll = NULL;
    
               // Zeiger auf den Documentinhalt holen
               if (SUCCEEDED(HTMLDocument->get_all(&pAll)) && pAll)
               {
                  // Anz. der Elemente auf der Seite holen
                  long iColLengh;
                  pAll->get_length(&iColLengh);
    
                  // die Elementliste durchsuchen
                  for (long i=0; i<iColLengh; i++)
                  {
                      TVariant vIndex = i;
                      IDispatch *pDisp = NULL;
    
                      if (SUCCEEDED(pAll->item(vIndex, vIndex, &pDisp)) && pDisp)
                      {
                         IHTMLInputElement *pInput = NULL;
    
                         // wenn das gefundene Element ein Input-Element ist
                         if (SUCCEEDED(pDisp->QueryInterface(IID_IHTMLInputElement, (LPVOID*)&pInput)) && pInput)
                         {
                            WideString wsElementName;
                            WideString wsElementValue;
                            WideString wsElementType;
                            // Name, Typ, Wert holen
                            pInput->get_name(&wsElementName);
                            pInput->get_value(&wsElementValue);
                            pInput->get_type(&wsElementType);
                            // ins Listview schreiben
                            ListItem = lvElements->Items->Add();
                            ListItem->Caption = wsElementName;
                            ListItem->SubItems->Add(wsElementType);
                            ListItem->SubItems->Add(wsElementValue);
                         }
    
                         pDisp->Release();
                      }
                  }
    
                  pAll->Release();
               }
            }
    
            HTMLDocument->Release();
         }
    }
    

    ➡ Das wäre doch mal wieder was für die FAQ, oder? 😉



  • F98 schrieb:

    Der Schlüssel liegt in der Zeile

    if (SUCCEEDED(pAll->item(vIndex, vIndex, &pDisp)) && pDisp)
    

    begraben. Über die einfache Angabe des Indexes kann mann schön in der Element-Liste rumiterieren.

    Muss der zweite Parameter denn zwingend ebenfalls inkrementiert werden?



  • Nöja, nicht unbedingt. Es geht auch, wenn man eine 2. TVariant-Variable mit 0 übergibt, aber im MSDN Beispiel wird ebenfals 2x der selben Index übergeben:

    http://msdn.microsoft.com/library/default.asp?url=/workshop/browser/mshtml/reference/ifaces/elementcollection/item_1.asp

    Ich denke mal, wenn vorne kein String steht, ist der 2. Parameter egal.


Anmelden zum Antworten