Knoten für die meisten Bilder bestellen?
-
22-09-2019 - |
Frage
Das mag ein bisschen kompliziert klingen, aber was ich tun möchte, ist alles zu finden <a>
s, die enthalten <img>
s So dass die Bilder, die im selben Knoten mit der größten Anzahl anderer Bilder sind, zuerst ausgewählt werden.
Zum Beispiel, wenn meine Seite so aussieht:
http://img684.imageshack.us/img684/5678/imagechart.gif
Wenn die blauen Quadrate sind <div>
S und die rosa Quadrate sind <img>
s dann die Mitte div
Enthält die meisten Bilder, dann werden diese Bilder zuerst ausgewählt. Da sie nicht tiefer verschachtelt sind, werden sie nur in der Reihenfolge erscheinen, dass sie auf der Seite sind. Als nächstes wird die erste Div ausgewählt (enthält die zweithäufigsten Bilder) und so weiter ... macht das Sinn?
Wir können es irgendwie rekursiv vorstellen. Zuerst die body
würde ausgewählt, da dies immer die meisten Bilder enthält, dann wird jedes der direkten Kinder untersucht, um herauszufinden, welche die meisten Bild -Nachkommen (nicht unbedingt direkt) enthält, dann gehen wir in diesen Knoten und wiederholen ...
Lösung 3
Aktuelle Lösung:
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);
}
}
Beispiel Verwendung:
private static void ProcessDocument(HtmlDocument doc, Uri baseUri) {
var linkNodes = new List<HtmlNode>(100);
BuildList(doc.DocumentNode, ref linkNodes);
// ...
Es ist jedoch ein bisschen ineffizient, weil es viel erzählt, aber na ja.
Andere Tipps
Sie könnten versuchen, die Anzahl von Bildern für jeden Knoten zu betrachten.
public static XmlNode FindNodeWithMostImages(XmlNodeList
Knoten) {
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; }
XPath 1.0 bietet nicht die Möglichkeit, eine Sammlung zu sortieren. Sie müssen nutzen XPath mit etwas anderem.
Hier ist ein Beispiel Xslt Lösung, die alle Elemente finden, die Nachkommen enthalten <img>
Elemente und sortiert sie dann nach der Anzahl ihres Nachkommens <img>
Elemente in absteigender Reihenfolge.
<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>
Ich war mir nicht klar aus Ihrer Frage und Beispielen, ob Sie ein Element mit Nachkommen finden möchten <img>
oder nur <a>
mit Nachkommen <img>
.
Wenn Sie nur finden wollten <a>
Elemente mit Nachkommen <img>
Elemente und dann die anpassen XPath in dem für jeden zur Auswahl: //a[descendant::img]