Gettig Htmlelement basé sur HtmlAgilityPack.HtmlNode

c# html html-agility-pack webbrowser-control

Question

J'utilise HtmlAgilityPack pour analyser le document html d'un contrôle Webbrowser. Je suis capable de trouver mon HtmlNode désiré, mais après avoir obtenu le HtmlNode, je veux relancer le HtmlElement correspondant dans le WebbrowserControl.Document.

En fait, HtmlAgilityPack analyse une copie hors ligne du document actif, alors que je souhaite accéder aux éléments en direct du contrôle navigateur Web pour accéder à certains attributs runtimeStyle tels que currentStyle ou runtimeStyle

HtmlAgilityPack.HtmlDocument doc = new HtmlAgilityPack.HtmlDocument();
doc.LoadHtml(webBrowser1.Document.Body.InnerHtml);
var some_nodes = doc.DocumentNode.SelectNodes("//p"); 
// this selection could be more sophisticated 
// and the answer shouldn't relay on it.
foreach (HtmlNode node in some_nodes)
{
   HtmlElement live_element = CorrespondingElementFromWebBrowserControl(node);
   // CorrespondingElementFromWebBrowserControl is what I am searching for
}

Si l'élément avait un attribut spécifique, cela pourrait être facile, mais je veux une solution qui fonctionne avec n'importe quel élément.

Aidez-moi s'il vous plaît que puis-je faire à ce sujet.

Réponse acceptée

l'attribut XPath de HtmlAgilityPack.HtmlNode affiche les nœuds sur le chemin d'accès de la racine au nœud. Par exemple, \div[1]\div[2]\table[0] . Vous pouvez parcourir ce chemin dans le document actif pour rechercher l'élément actif correspondant. Cependant, ce chemin peut ne pas être précis car HtmlAgilityPack supprime certaines balises comme <form> puis avant d'utiliser cette solution, rajoutez les balises omises à l'aide de

HtmlNode.ElementsFlags.Remove("form");

struct DocNode  
{
    public string Name;
    public int Pos;
}
///// structure to hold the name and position of each node in the path

La méthode suivante trouve l'élément live en fonction de XPath

    static public HtmlElement GetLiveElement(HtmlNode node, HtmlDocument doc)
    {
        var pattern = @"/(.*?)\[(.*?)\]"; // like div[1]
        // Parse the XPath to extract the nodes on the path
        var matches = Regex.Matches(node.XPath, pattern); 
        List<DocNode> PathToNode = new List<DocNode>();
        foreach (Match m in matches) // Make a path of nodes
        {
            DocNode n = new DocNode();
            n.Name = n.Name = m.Groups[1].Value;
            n.Pos = Convert.ToInt32(m.Groups[2].Value)-1;
            PathToNode.Add(n); // add the node to path 
        }

        HtmlElement elem = null; //Traverse to the element using the path
        if (PathToNode.Count > 0)
        {
            elem = doc.Body; //begin from the body
            foreach (DocNode n in PathToNode)
            {
                //Find the corresponding child by its name and position
                elem = GetChild(elem, n);                    
            }
        }
        return elem;
    }

le code de la méthode GetChild utilisée ci-dessus

    public static HtmlElement GetChild(HtmlElement el, DocNode node)
    {
        // Find corresponding child of the elemnt 
        // based on the name and position of the node
        int childPos = 0;
        foreach (HtmlElement child in el.Children)
        {
            if (child.TagName.Equals(node.Name, 
               StringComparison.OrdinalIgnoreCase))
            {
                if (childPos == node.Pos)
                {
                    return child;
                }
                childPos++;
            }                
        }
        return null;
    }

Réponse populaire

HtmlAgilityPack ne peut définitivement pas fournir un accès direct aux nœuds en HTML live. Comme vous avez dit qu'il n'y a pas de style / classe / id distinct sur l'élément, vous devez parcourir les nœuds manuellement et trouver des correspondances.

En supposant que le langage HTML soit raisonnablement valide (pour que navigateur et HtmlAgilityPack effectuent la normalisation de la même manière), vous pouvez parcourir des paires d'éléments en partant de la racine des deux arbres et en sélectionnant le même nœud enfant.

Fondamentalement, vous pouvez construire XPath "basé sur la position" en nœud dans un arbre et le sélectionner dans un autre arbre. Xpath ressemblerait à quelque chose comme ça (selon que vous voulez faire attention aux positions ou au nom du noeud):

 "/*[1]/*[4]/*[2]/*[7]"
 "/body/div[2]/span[1]/p[3]"

Pas:

  1. En utilisant HtmlNode vous avez trouvé collecter tous les nœuds parents jusqu'à la racine.
  2. Obtenir la racine de l'élément HTML dans le navigateur
  3. pour chaque niveau d'enfants, trouvez la position de l'enfant correspondant dans la collection HtmlNodes à l'étape 1 dans son parent, puis recherchez HtmlElement en direct parmi les enfants du noeud actif en cours.
  4. Déplacez-vous sur l'enfant nouvellement trouvé et revenez à 3 jusqu'à trouver le noeud que vous recherchez.


Related

Sous licence: CC-BY-SA with attribution
Non affilié à Stack Overflow
Sous licence: CC-BY-SA with attribution
Non affilié à Stack Overflow