Заказы узлов большинством изображений?
-
22-09-2019 - |
Вопрос
Это может звучать немного сложно, но я хочу найти все <a>
S, которые содержат <img>
S так, что изображения, которые находятся в одном узле с наибольшим количеством других изображений, первыми выбираются.
Например, если моя страница выглядит так:
http://img684.imageshack.us/img684/5678/imagechart.gif
Если синие квадраты <div>
S и розовые квадраты <img>
S затем середина div
Содержит большинство изображений, затем сначала выбираются эти изображения. Поскольку они не вложены глубже, они просто появляются в том порядке, в котором они находятся на странице. Далее выбран первый Div (содержит 2 -е место в большинстве изображений), и так далее ... это имеет смысл?
Мы можем думать об этом вроде рекурсивно. Сначала body
будет выбран, так как это всегда будет содержать большинство изображений, тогда каждый из прямых детей исследуется, чтобы увидеть, что содержит наибольшее количество потомков (не обязательно прямое), тогда мы переходим в этот узел и повторяем ...
Решение 3
Текущее решение:
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);
// ...
Это немного неэффективно, потому что он много рассказывает, но хорошо.
Другие советы
Вы можете попробовать посмотреть на количество изображений для каждого узла.
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; }
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>
Элементы с потомком <img>
элементы, затем отрегулируйте Xpath в для каждого выбирать: //a[descendant::img]