4

これは少し複雑に聞こえるかもしれませんが、私がやりたいことは、<a>s を含むすべての s を見つけ<img>て、他の画像の数が最も多い同じノードにある画像が最初に選択されるようにすることです。

たとえば、私のページが次のようになっているとします。

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

青い四角が<div>で、ピンクの四角が である<img>場合、中央divに最も多くの画像が含まれており、それらの画像が最初に選択されます。それらはそれ以上ネストされていないため、ページ上にある順序で表示されます。次に、最初の div が選択されます (2 番目に多い画像が含まれます)。

一種の再帰的に考えることができます。最初に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>

私はあなたの質問と例から、子孫を持つ要素を見つけたいのか<img>、単に<a>子孫だけを見つけたいのかはっきりしませんでした<img>

<a>子孫要素を持つ要素だけを見つけたい場合は、for-eachでXPATH<img>を調整して選択します。//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 に答える