4

这听起来可能有点复杂,但我想做的是找到所有<a>包含<img>s 的 s ,以便首先选择位于同一节点中且其他图像数量最多的图像。

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

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

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

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

4

3 回答 3

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;
    }
于 2010-01-03T23:09:31.287 回答
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>

从您的问题和示例中,我不清楚您是要查找任何带有 descendant 的元素<img>还是仅<a>带有 descendant的元素<img>

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

于 2010-01-04T02:23:20.643 回答
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);
        // ...

虽然它有点低效,因为它做了很多叙述,但是哦,好吧。

于 2010-01-12T06:51:03.880 回答