Benutzer mit den meisten Antworten
Hilfe bei LINQ Abfrage von HTML Element

Frage
-
Hallo,
ich habe eine LINQ Abfrage für ein bestimmtes HTML Div-Element mit dem class-Attribut smallfont. Das klappt auch ohne Probleme, nur kann es vorkommen das zweimal dieselben Div Elemente hintereinander vorkommen. Hier möchte ich nur das erste Element selektieren.
var boards = (from tbody in documentNode.Descendants("tbody") where tbody.Attributes.Contains("id") && tbody.Attributes["id"].Value.StartsWith("collapseobj_forumbit_") from td in tbody.Descendants("td") where td.Attributes.Contains("class") && td.Attributes["class"].Value == "alt1Active" from a in td.Descendants("a") where a.HasChildNodes && a.FirstChild.Name == "strong" from div in td.Descendants("div") // Hier nur den ersten Treffer selektieren where div.Attributes.Contains("class") && div.Attributes["class"].Value == "smallfont" // Hier nur den ersten Treffer selektieren select new BoardViewModel() { Name = a.FirstChild.InnerText, Uri = a.GetAttributeValue("href", string.Empty), Description = div.InnerText }).ToArray();
Der HTML Code:
<tbody id="collapseobj_forumbit_3" style=""> <td class="alt1Active" align="left" id="f23"> <div> <a href="#"><strong>Trainingsforum</strong></a> </div> <div class="smallfont">Das hier soll selektiert werden</div> <div class="smallfont" style="margin-top:0px">Das soll nicht selektiert werden</div>
Bitte um Hilfe! :)
Antworten
-
hab gerade das Windows Phone SDk nicht hier, aber ich würde es erstmal ganz einfach im Select new mit folgendem versuchen:
Description =(div.InnerText ).First()
ansonsten den längeren weg.
var boards = (from tbody in documentNode.Descendants("tbody") where tbody.Attributes.Contains("id") && tbody.Attributes["id"].Value.StartsWith("collapseobj_forumbit_") from td in tbody.Descendants("td") where td.Attributes.Contains("class") && td.Attributes["class"].Value == "alt1Active" from a in td.Descendants("a") where a.HasChildNodes && a.FirstChild.Name == "strong" select new BoardViewModel() { Name = a.FirstChild.InnerText, Uri = a.GetAttributeValue("href", string.Empty), Description = ( from div in td.Descendants("div") // Hier nur den ersten Treffer selektieren where div.Attributes.Contains("class") && div.Attributes["class"].Value == "smallfont" // Hier nur den ersten Treffer selektieren select div.InnerText ).First() }).ToArray();
mfg
Shmoo
Beende meine FIAE Ausbiildung mit dem Prüfungsteil A am 20.06.2012. Suche Job im MS Umfeld in Wuppertal und Umgebung!
- Bearbeitet Lennart F Montag, 11. Juni 2012 16:20
- Als Antwort vorgeschlagen Robert Breitenhofer Montag, 11. Juni 2012 16:28
- Als Antwort markiert Robert Breitenhofer Dienstag, 12. Juni 2012 06:46
-
Vielen Dank für eure Hilfe!
Das hier ist die endgültige Lösung:
var boards = (from tbody in documentNode.Descendants("tbody") where tbody.Attributes.Contains("id") && tbody.Attributes["id"].Value.StartsWith("collapseobj_forumbit_") from td in tbody.Descendants("td") where td.Attributes.Contains("class") && td.Attributes["class"].Value == "alt1Active" from a in td.Descendants("a") where a.HasChildNodes && a.FirstChild.Name == "strong" select new BoardViewModel() { Name = a.FirstChild.InnerText, Uri = a.GetAttributeValue("href", string.Empty), Description = (from div in td.Descendants("div") where div.Attributes.Contains("class") && div.Attributes["class"].Value == "smallfont" select div.InnerText).FirstOrDefault() }).ToArray();
Ich muss bei Description FirstOrDefault() verwenden, da es auch möglich sein kann das welche keine Description haben, also kein Div mit der Klasse "smallfont"!
- Als Antwort markiert Robert Breitenhofer Freitag, 15. Juni 2012 08:27
Alle Antworten
-
Hallo websocialist,
Poste mal die URL der Seite hier damit man das ganze HTML sehen kann.
Danke und Grüße,
Robert
Robert Breitenhofer, MICROSOFT
Bitte haben Sie Verständnis dafür, dass im Rahmen dieses Forums, welches auf dem Community-Prinzip „Entwickler helfen Entwickler“ beruht, kein technischer Support geleistet werden kann oder sonst welche garantierten Maßnahmen seitens Microsoft zugesichert werden können. -
Hier ist die URL: http://www.muskelschmiede.de/forum/
- Bearbeitet Robert Breitenhofer Dienstag, 29. Mai 2012 12:36 URL als Link
-
Hallo websocialist,
Konkret, welches Ergebnis erwartest Du? Folgendes (wurde mit .ToArray[0] erzeugt)?
[Code]
private void button2_Click(object sender, RoutedEventArgs e) { HtmlWeb.LoadAsync("http://www.muskelschmiede.de/forum/", HtmlWeb_Loaded2); } private void HtmlWeb_Loaded2(object sender, HtmlDocumentLoadCompleted e) { if (e.Error == null) { HtmlDocument doc = e.Document; var node = (from tbody in doc.DocumentNode.Descendants("tbody") where tbody.Attributes.Contains("id") && tbody.Attributes["id"].Value.StartsWith("collapseobj_forumbit_") from td in tbody.Descendants("td") where td.Attributes.Contains("class") && td.Attributes["class"].Value == "alt1Active" from a in td.Descendants("a") where a.HasChildNodes && a.FirstChild.Name == "strong" from div in td.Descendants("div") // Hier nur den ersten Treffer selektieren where div.Attributes.Contains("class") && div.Attributes["class"].Value == "smallfont" // Hier nur den ersten Treffer selektieren select new BoardViewModel() { Name = a.FirstChild.InnerText, Uri = a.GetAttributeValue("href", string.Empty), Description = div.InnerText }).ToArray()[0]; //select tbody).First(); } } public class BoardViewModel { public string Name { get; set; } public string Uri { get; set; } public string Description { get; set; } }
Grüße,
Robert
Robert Breitenhofer, MICROSOFT
Bitte haben Sie Verständnis dafür, dass im Rahmen dieses Forums, welches auf dem Community-Prinzip „Entwickler helfen Entwickler“ beruht, kein technischer Support geleistet werden kann oder sonst welche garantierten Maßnahmen seitens Microsoft zugesichert werden können. -
Mein erwartetes Ergebnis sieht man am besten an folgenden HTML.
<tbody id="collapseobj_forumbit_3" style=""> <td class="alt1Active" align="left" id="f23"> <div> <a href="#"><strong>Trainingsforum</strong></a> </div> <div class="smallfont">Alles rund ums Muskelaufbau-Training, alle Trainingsmethoden, Trainingspläne und Übungen.</div> <!-- Nur diese Node selektieren --> <div class="smallfont" style="margin-top:0px">Unterforen: Anfänger, Training@home</div> <td class="alt1Active" align="left" id="f45"> <div> <a href="#"><strong>Trainingspläne</strong></a> </div> <div class="smallfont">Präsentation und Fragen zu Trainigsplänen und Programmen.</div> </td>
Es sind zwei td-Knoten mit dem class-Attribut "alt1Active vorhanden. Beide Knoten enthalten ein div-Element mit dem class-Attribut "smallfont", der erste Knoten hat dieses Element aber zweimal. Hier möchte ich nur den Inhalt des ersten div-Elements selektieren.
Folgendes Ergebnis erwarte ich:
BoardViewModel[0]:
Name: Traininsforum
Description: Alles rund ums Muskelaufbau-Training, alle Trainingsmethoden, Trainingspläne und Übungen.
Url: #
BoardViewModel[1]:
Name: Trainingspläne
Description: Präsentation und Fragen zu Trainigsplänen und Programmen.
Url: #
Mit meinem bisherigen Code erhalte ich aber zum ersten Treffer noch einen zweiten, mit einer anderen Description:
BoardViewModel[0]:
Name: Traininsforum
Description: Alles rund ums Muskelaufbau-Training, alle Trainingsmethoden, Trainingspläne und Übungen.
Url: #
BoardViewModel[1]:
Name: Trainingsforum
Description: Unterforen: Anfänger, Training@home
Url: #
BoardViewModel[2]:
Name: Trainingspläne
Description: Präsentation und Fragen zu Trainigsplänen und Programmen.
Url: #- Bearbeitet websocialist Dienstag, 29. Mai 2012 17:57
-
Mit meinem bisherigen Code erhalte ich aber zum ersten Treffer noch einen zweiten, mit einer anderen Description:
BoardViewModel[0]:
Name: Trainingsforum
Description: Alles rund ums Muskelaufbau-Training, alle Trainingsmethoden, Trainingspläne und Übungen.
Url: #
BoardViewModel[1]:
Name: Trainingsforum
Description: Unterforen: Anfänger, Training@home
Url: #
BoardViewModel[2]:
Name: Trainingspläne
Description: Präsentation und Fragen zu Trainigsplänen und Programmen.
Url: #
Hallo websocialist,
Ich bekomme dasselbe wie im Zitat aber mit folgendem Code (also nicht wie in Deinem Originalpost …siehe bei mir die && (td.Id == "f23" || td.Id == "f45")):
private void HtmlWeb_Loaded2(object sender, HtmlDocumentLoadCompleted e) { if (e.Error == null) { HtmlDocument doc = e.Document; var node = (from tbody in doc.DocumentNode.Descendants("tbody") where tbody.Attributes.Contains("id") && tbody.Attributes["id"].Value.StartsWith("collapseobj_forumbit_") from td in tbody.Descendants("td") where td.Attributes.Contains("class") && td.Attributes["class"].Value == "alt1Active" && (td.Id == "f23" || td.Id == "f45") from a in td.Descendants("a") where a.HasChildNodes && a.FirstChild.Name == "strong" from div in td.Descendants("div") // Hier nur den ersten Treffer selektieren where div.Attributes.Contains("class") && div.Attributes["class"].Value == "smallfont"// Hier nur den ersten Treffer selektieren select new BoardViewModel() { Name = a.FirstChild.InnerText, Uri = a.GetAttributeValue("href", string.Empty), Description = div.InnerText }).ToArray(); } } public class BoardViewModel { public string Name { get; set; } public string Uri { get; set; } public string Description { get; set; } }
Zeig mal Deinen Code mit dem Du das was im Zitat steht, bekommst.
Danke und Grüße,
Robert
Robert Breitenhofer, MICROSOFT
Bitte haben Sie Verständnis dafür, dass im Rahmen dieses Forums, welches auf dem Community-Prinzip „Entwickler helfen Entwickler“ beruht, kein technischer Support geleistet werden kann oder sonst welche garantierten Maßnahmen seitens Microsoft zugesichert werden können. -
hab gerade das Windows Phone SDk nicht hier, aber ich würde es erstmal ganz einfach im Select new mit folgendem versuchen:
Description =(div.InnerText ).First()
ansonsten den längeren weg.
var boards = (from tbody in documentNode.Descendants("tbody") where tbody.Attributes.Contains("id") && tbody.Attributes["id"].Value.StartsWith("collapseobj_forumbit_") from td in tbody.Descendants("td") where td.Attributes.Contains("class") && td.Attributes["class"].Value == "alt1Active" from a in td.Descendants("a") where a.HasChildNodes && a.FirstChild.Name == "strong" select new BoardViewModel() { Name = a.FirstChild.InnerText, Uri = a.GetAttributeValue("href", string.Empty), Description = ( from div in td.Descendants("div") // Hier nur den ersten Treffer selektieren where div.Attributes.Contains("class") && div.Attributes["class"].Value == "smallfont" // Hier nur den ersten Treffer selektieren select div.InnerText ).First() }).ToArray();
mfg
Shmoo
Beende meine FIAE Ausbiildung mit dem Prüfungsteil A am 20.06.2012. Suche Job im MS Umfeld in Wuppertal und Umgebung!
- Bearbeitet Lennart F Montag, 11. Juni 2012 16:20
- Als Antwort vorgeschlagen Robert Breitenhofer Montag, 11. Juni 2012 16:28
- Als Antwort markiert Robert Breitenhofer Dienstag, 12. Juni 2012 06:46
-
Hallo Der_Shmoo,
Dein Code ist ist die Lösung aber ich brauche noch immer die Erweiterung && (td.Id == "f23" || td.Id == "f45") in der Zeile where td.Attributes.Contains("class") && td.Attributes["class"].Value == "alt1Active" && (td.Id == "f23" || td.Id == "f45") damit ich in boards folgendes bekomme:
Wenn ich && (td.Id == "f23" || td.Id == "f45") rauslasse dann komme ich an den Breakpoint nicht an.
Grüße,
Robert
Robert Breitenhofer, MICROSOFT
Bitte haben Sie Verständnis dafür, dass im Rahmen dieses Forums, welches auf dem Community-Prinzip „Entwickler helfen Entwickler“ beruht, kein technischer Support geleistet werden kann oder sonst welche garantierten Maßnahmen seitens Microsoft zugesichert werden können. -
Hatte mich nur an den Code // Hier nur denErsten gehalten, da ich auch kein VS hier habe konnte ich das eh nicht nachprüfen. gehe aber davon aus das du recht hast. solange es nun fluppt ist ja alles bestens.
Hast du dies zufällig ausprobiert ob die ganz kurze Version funktioniert (Description =(div.InnerText).First()) ?
würd mich mal interessieren..... aber ohne vs ist man so nackig^^
mfg
Shmoo
Beende meine FIAE Ausbiildung mit dem Prüfungsteil A am 20.06.2012. Suche Job im MS Umfeld in Wuppertal und Umgebung!
-
Hast du dies zufällig ausprobiert ob die ganz kurze Version funktioniert (Description =(div.InnerText).First()) ?
würd mich mal interessieren...
Hallo Der_Shmoo,
Mit der folgenden Zeile bekomme ich bei der Description dasselbe wie bei Name:
Description=(from div in td.Descendants("div") select div.InnerText).First()
[C#]
var boards = (from tbody in doc.DocumentNode.Descendants("tbody") where tbody.Attributes.Contains("id") && tbody.Attributes["id"].Value.StartsWith("collapseobj_forumbit_") from td in tbody.Descendants("td") where td.Attributes.Contains("class") && td.Attributes["class"].Value == "alt1Active" && (td.Id == "f23" || td.Id == "f45") from a in td.Descendants("a") where a.HasChildNodes && a.FirstChild.Name == "strong" select new BoardViewModel() { Name = a.FirstChild.InnerText, Uri = a.GetAttributeValue("href", string.Empty), Description=(from div in td.Descendants("div") select div.InnerText).First() }).ToArray();
[BILD]
Nur wo smallfont auftaucht hat man die Description:
Einfach Description =(div.InnerText ).First() funktioniert nicht, da er nicht weiß wer div ist.
<tbody id="collapseobj_forumbit_3" style=""> <td class="alt1Active" align="left" id="f23"> <div> <a href="#"><strong>Trainingsforum</strong></a> </div> <div class="smallfont">Alles rund ums Muskelaufbau-Training, alle Trainingsmethoden, Trainingspläne und Übungen.</div> <!-- Nur diese Node selektieren --> <div class="smallfont" style="margin->Unterforen: Anfänger, Training@home</div> <td class="alt1Active" align="left" id="f45"> <div> <a href="#"><strong>Trainingspläne</strong></a> </div> <div class="smallfont">Präsentation und Fragen zu Trainigsplänen und Programmen.</div> </td>
Grüße,
Robert
Robert Breitenhofer, MICROSOFT
Bitte haben Sie Verständnis dafür, dass im Rahmen dieses Forums, welches auf dem Community-Prinzip „Entwickler helfen Entwickler“ beruht, kein technischer Support geleistet werden kann oder sonst welche garantierten Maßnahmen seitens Microsoft zugesichert werden können. -
Hallo websocialist,
Ich gehe davon aus, dass die Antwort Dir weitergeholfen hat.
Solltest Du noch "Rückfragen" dazu haben, so gib uns bitte Bescheid.Grüße,
RobertRobert Breitenhofer, MICROSOFT
Bitte haben Sie Verständnis dafür, dass im Rahmen dieses Forums, welches auf dem Community-Prinzip „Entwickler helfen Entwickler“ beruht, kein technischer Support geleistet werden kann oder sonst welche garantierten Maßnahmen seitens Microsoft zugesichert werden können. -
Einfach Description =(div.InnerText ).First() funktioniert nicht, da er nicht weiß wer div ist.
Stimmt.... da hätte man auch ohne VS drauf kommen können^^.
danke für die antwort und das ausprobieren.
MfG
Shmoo
Beende meine FIAE Ausbiildung mit dem Prüfungsteil A am 20.06.2012. Suche Job im MS Umfeld in Wuppertal und Umgebung!
-
Vielen Dank für eure Hilfe!
Das hier ist die endgültige Lösung:
var boards = (from tbody in documentNode.Descendants("tbody") where tbody.Attributes.Contains("id") && tbody.Attributes["id"].Value.StartsWith("collapseobj_forumbit_") from td in tbody.Descendants("td") where td.Attributes.Contains("class") && td.Attributes["class"].Value == "alt1Active" from a in td.Descendants("a") where a.HasChildNodes && a.FirstChild.Name == "strong" select new BoardViewModel() { Name = a.FirstChild.InnerText, Uri = a.GetAttributeValue("href", string.Empty), Description = (from div in td.Descendants("div") where div.Attributes.Contains("class") && div.Attributes["class"].Value == "smallfont" select div.InnerText).FirstOrDefault() }).ToArray();
Ich muss bei Description FirstOrDefault() verwenden, da es auch möglich sein kann das welche keine Description haben, also kein Div mit der Klasse "smallfont"!
- Als Antwort markiert Robert Breitenhofer Freitag, 15. Juni 2012 08:27