Сравнить список XPath, чтобы найти ближайший к другому узлу? - PullRequest
0 голосов
/ 08 марта 2012

У меня есть следующий узел

"/html[1]/body[1]/div[1]/div[1]/div[3]/div[1]/div[7]/p[1]/#text[1]"

Как я могу понять, что последний из них самый близкий?

"/html[1]/body[1]/div[1]/div[1]/div[3]/div[1]/div[4]/div[1]/img[1]"
"/html[1]/body[1]/div[1]/div[1]/div[3]/div[1]/div[4]/div[3]/a[1]/img[1]"
"/html[1]/body[1]/div[1]/div[1]/div[3]/div[1]/div[4]/div[3]/a[2]/img[1]"
"/html[1]/body[1]/div[1]/div[1]/div[3]/div[1]/div[4]/div[5]/img[1]"
"/html[1]/body[1]/div[1]/div[1]/div[3]/div[1]/div[5]/div[1]/img[1]"

Это не всегда будет последним.

Вот как я туда попал:

protected string GuessThumbnail(HtmlDocument document)
{
    HtmlNode root = document.DocumentNode;
    IEnumerable<string> result = new List<string>();

    HtmlNode description = root.SelectSingleNode(DescriptionPredictiveXPath);
    if (description != null) // in this case, we predict relevant images are the ones closest to the description text node.
    {
        HtmlNode node = description.ParentNode;
        while (node != null)
        {
            string path = string.Concat(node.XPath, ImageXPath);
            node = node.ParentNode;
            IEnumerable<HtmlNode> nodes = root.SelectNodesOrEmpty(path);

            // find the image tag that's closest to the text node.
            if (nodes.Any())
            {
                var xpaths = nodes.Select(n => n.XPath);
                xpaths.ToList();

                // return closest
            }
        }
    }
    // figure some other way to do it

    throw new NotImplementedException();
}

Ответы [ 2 ]

0 голосов
/ 08 марта 2012

Понравилось ли это:

    protected string GuessThumbnail(HtmlDocument document)
    {
        HtmlNode root = document.DocumentNode;
        HtmlNode description = root.SelectSingleNode(DescriptionPredictiveXPath);

        if (description != null)
        {
            // in this case, we predict relevant images are the ones closest to the description text node.
            HtmlNode parent = description.ParentNode;
            while (parent != null)
            {
                string path = string.Concat(parent.XPath, ImageXPath);
                IList<HtmlNode> images = root.SelectNodesOrEmpty(path).ToList();

                // find the image tag that's closest to the text node.
                if (images.Any())
                {
                    HtmlNode descriptionOutermost = description.ParentNodeUntil(parent); // get the first child towards the description from the parent node.
                    int descriptionIndex = descriptionOutermost.GetIndex(); // get the index of the description's outermost element.

                    HtmlNode closestToDescription = null;
                    int distanceToDescription = int.MaxValue;

                    foreach (HtmlNode image in images)
                    {
                        int index = image.ParentNodeUntil(parent).GetIndex(); // get the index of the image's outermost element.
                        if (index > descriptionIndex)
                        {
                            index *= -1;
                        }
                        int distance = descriptionIndex - index;
                        if (distance < distanceToDescription)
                        {
                            closestToDescription = image;
                            distanceToDescription = distance;
                        }
                    }
                    if (closestToDescription != null)
                    {
                        string source = closestToDescription.Attributes["src"].Value;
                        return source;
                    }
                }

                parent = parent.ParentNode;
            }
        }
        // figure some other way to do it

        throw new NotImplementedException();
    }


public static HtmlNode ParentNodeUntil(this HtmlNode node, HtmlNode parent)
{
    while (node.ParentNode != parent)
    {
        node = node.ParentNode;
    }
    return node;
}
public static int GetIndex(this HtmlNode node)
{
    return node.ParentNode.ChildNodes.IndexOf(node);
}
0 голосов
/ 08 марта 2012

Рассмотрите возможность назначения "позиции во всем дереве в порядке глубины" для каждого узла. Таким образом, сравнение двух узлов будет очень простым.

Если вы можете прикрепить произвольные данные к своим узлам - добавьте их напрямую. В противном случае есть словарь всех узлов для размещения карты.

Обратите внимание, что в зависимости от того, сколько раз вам нужно сделать это сравнение, этот подход может быть медленным для вас, но он должен быть прост в реализации и измерении, он соответствует вашим требованиям.

...