按大多数图像排序节点?

时间:2010-01-03 22:12:36

标签: c# xpath html-agility-pack

这可能听起来有点复杂,但我想要做的是找到包含<a>的所有<img> s,使得同一节点中的图像具有最多的其他图像首选。

例如,如果我的页面如下所示:

http://img684.imageshack.us/img684/5678/imagechart.gif

如果蓝色方块为<div> s且粉红色方块为<img> s,则中间div包含最多图像,则首先选择这些图像。由于它们没有嵌套得更深,所以它们只是按照它们在页面上的顺序出现。接下来选择第一个div(包含第二个最多的图像),依此类推......这有意义吗?

我们可以递归地想到它。首先选择body,因为它总是包含最多的图像,然后检查每个直接子项以查看哪个包含最多的图像后代(不一定是直接的),然后我们进入该节点,然后重复...

3 个答案:

答案 0 :(得分:1)

您可以尝试查看每个节点的图像数量。

    public static XmlNode FindNodeWithMostImages(XmlNodeList
     

节点)           {

        var greatestImageCount = 0;
        XmlNode nodeWithMostImages = null;

        foreach (XmlNode node in nodes)
        {
            var currentNode = node;
            var currentNodeImageCount = node.SelectNodes("*/child::img").Count;

            if (currentNodeImageCount > greatestImageCount)
            {
                greatestImageCount = currentNodeImageCount;
                nodeWithMostImages = node;
            }
        }

        return nodeWithMostImages;
    }

答案 1 :(得分:1)

XPATH 1.0不提供对集合进行排序的功能。您需要将 XPATH 与其他内容一起使用。

以下是一个示例 XSLT 解决方案,它将查找包含后代<img>元素的所有元素,然后按降序排列后代<img>元素的数量对它们进行排序

    

    <xsl:template match="/">
        <!--if only want <a>, then select //a[descendant::img] -->
        <xsl:for-each select="//*[descendant::img]">
            <xsl:sort select="count(descendant::img)" order="descending" />

                <!--Example output to demonstrate what elements have been selected-->
                <xsl:value-of select="name()"/><xsl:text> has </xsl:text>
                <xsl:value-of select="count(.//img)" />  
                <xsl:text> descendant images                     
                </xsl:text>

        </xsl:for-each>

    </xsl:template>

</xsl:stylesheet>

我不清楚您的问题和示例是否要查找带有后代<img>的任何元素,或仅查找带有后代<a>的{​​{1}}元素。

如果您只想查找带有后代<img>元素的<a>元素,请调整 for-each 中的 XPATH 以选择: <img>

答案 2 :(得分:0)

目前的解决方案:

    private static int Count(HtmlNodeCollection nc) {
        return nc == null ? 0 : nc.Count;
    }

    private static void BuildList(HtmlNode node, ref List<HtmlNode> list) {
        var sortedNodes = from n in node.ChildNodes
                          orderby Count(n.SelectNodes(".//a[@href and img]")) descending
                          select n;
        foreach (var n in sortedNodes) {
            if (n.Name == "a") list.Add(n);
            else if (n.HasChildNodes) BuildList(n, ref list);
        }
    }

使用示例:

    private static void ProcessDocument(HtmlDocument doc, Uri baseUri) {
        var linkNodes = new List<HtmlNode>(100);
        BuildList(doc.DocumentNode, ref linkNodes);
        // ...

这有点效率低,但因为它做了大量的重述,但很好。