AngleSharp return span id - c#

I'm trying to get a grip on AngleSharp by returning a specific part of an html.
So far that's my Code:
using (WebClient client = new WebClient())
{
string htmlCode = client.DownloadString("http://www.planetradio.de/music/trackfinder.html");
var parser = new HtmlParser();
var document = parser.Parse(htmlCode);
var blueListItemsLinq = document.All.Where(m => m.LocalName == "span id" && m.ClassList.Contains("headerTracklistCurrentSongArtist"));
foreach (var item in blueListItemsLinq)
label.Content = item;
}
What i want it to return is the current Artist which should be in the html under:
<div id="headerTracklistCurrentSong">
<span id="headerTracklistCurrentSongArtist">Olly Murs</span>
<span id="headerTracklistCurrentSongTitle">Kiss Me</span>
But i seem to have made a mistake....so i'd be glad if someone could help me here and explain it to me...
Thanks in advance to everyone answering. :)

The span elements are parsed as AngleSharp.Dom.Html.HtmlSpanElement
so your query should be:
var blueListItemsLinq = document.All.Where(m => m.LocalName == "span" && m.Id == "headerTracklistCurrentSongArtist");
Then you can get the text/values like this:
foreach (var item in blueListItemsLinq)
{
label.Content = item.TextContent; // "Olly Murs"
var child = item.FirstChild as AngleSharp.Dom.Html.IHtmlAnchorElement;
var text = child.Text; // "Olly Murs"
var path = child.PathName; // "/music/trackfinder.html"
}
UPDATED
Since the currnt Artist names are shown in the table at "planetradio.de/music/trackfinder.html", you can get the names like this:
var hitfinderTable = document.All.Where(m => m.Id == "hitfindertable").First() as AngleSharp.Dom.Html.IHtmlTableElement;
foreach (var row in hitfinderTable.Rows)
{
var artistName = row.Cells[2].TextContent;
}

Related

Checking for existing records on database wen i call web api

I am calling a web api and saving the records on the database through the controller, i want each time im calling the api to check if the record exists in the database if yes then dont save, if not then save.
var client = new WebClient();
var text = client.DownloadString("https://www.test.com/api/all-users?name=testusername%20&pass=334432");
var wclients = JsonConvert.DeserializeObject<dynamic>(text);
List<apicli> list1 = new List<apicli>();
var clie = new apicli();
if (wclients.message == "success")
{
var data = wclients.data;
//var account = wclients.account;
ViewBag.test = data;
foreach(var item in ViewBag.test)
{
clie.Email = item.email;
clie.Name = item.name;
clie.Aff = item.affiliated_id;
foreach(var item1 in #item.account.real)
{
clie.Login = item1.login;
clie.password = item1.pass;
}
list1.Add(clie);
db.apiclis.AddRange(list1);
db.SaveChanges();
};
}
I would assume you need something like this, although you need to check what is the unique id of each record:
foreach(var item in data){
var c = new apicli {
Email = item.email,
Name = item.name,
Aff = item.affiliated_id
Login = item.account.real.LastOrDefault()?login??"",
Login = item.account.real.LastOrDefault()?pass??""
}
if(!db.apiclis.Any(a => a.Email == c.Email && a.Name == c.Name && a.Aff == c.Aff)){
db.apiclis.Add(c);
}
}
Here I assume that email+name+aff = unique identificator.

Elastic Search Fetch Exact document

I've been trying to fetch document from elastic search on the basis of two fields "sAMAccountName" and "Container" but no luck.
enter image description here
What i want is a document where both attributes are exactly equally to my given value.
This is something I've been doing
It gave me results where user contain's the given property but i want exact match.
string container = getUserContainer(identityStore.ConnectionString);
var searchRequest = new Nest.SearchRequest();
searchRequest.Size = 10000;
searchRequest.Query = GetQuery(knownAttributes.SamAccountName, userName) && GetQuery("Container", container);
var searchResults = elasticSearch.Search<Dictionary<string,object>>(searchRequest);
return null;
private Nest.MatchQuery GetQuery(Nest.Field field, string query)
{
var matchQuery = new Nest.MatchQuery();
matchQuery.Field = field;
matchQuery.Query = query;
matchQuery.Operator = Operator.And;
r
eturn matchQuery;
}
Try this:
IQueryResponse<T> result = client.Search<T>(s => s
.Size(1)
.Query(q => q.Term("field1", value1) && q.Term("field2", value2))
.Index("myindex")
.Type("mytype")
);
if (result.Documents.Count<T>() > 0)
{
//do something
}

c# Find out variating column in html table

How can I find out the sixth column in this html table (using for example HTML Agility Pack or Regex)?
<tr><td>So, 22.05.16</td><td>1</td><td>D</td><td>E</td><td>190</td><td>DifferentThings</td></tr>
In the last column could stand anything and this is only one row of many, so I want the full last column with every entry.
Edit:
If there is an blank
<td></td>
in the 6th row I always get an
System.NullReferenceException
What shoud I do now?
innerTextOfLastCell = lastTdCell.InnerText.Trim();
is causing the error
Edit:
Solved it!
Just typed:
if (lastTdCell != null) //Not lastTdCell.InnerText.Trim()!
{
innerTextOfLastCell = lastTdCell.InnerText.Trim();
s = s + innerTextOfLastCell + "\n";
run.Text = s;
}
else
{
s = s + "\n\n";
run.Text = s;
}
Using HtmlAgilityPack, this should work regardless of the number of columns the table has.
var html = new HtmlDocument();
html.LoadHtml("<table><tr><td>So, 22.05.16</td><td>1</td><td>D</td><td>E</td><td>190</td><td>DifferentThings</td></tr></table>");
var root = html.DocumentNode;
var tableNodes = root.Descendants("table");
var innerTextOfLastCell = string.Empty;
foreach (var tbs in tableNodes.Select((tbNodes, i) => new { tbNodes = tbNodes, i = i }))
{
var trs = tbs.tbNodes.Descendants("tr");
foreach (var tr in trs.Select((trNodes, j) => new { trNodes = trNodes, j = j }))
{
var tds = tr.trNodes.Descendants("td");
var lastTdCell = tds.LastOrDefault();
innerTextOfLastCell = lastTdCell.InnerText.Trim();
}
}
[edit]
If you did want to use the other option from How to get the value from a specific cell C# Html-Agility-Pack, then you could try the following code:
HtmlNode lastTdnode = root.SelectSingleNode("//table[1]/tr[last()]/td[last()]");
This will give you the last <td> from the last <tr> from the first <table>
If you wanted the sixth cell you can use something like this, but will give you the same result as above:
HtmlNode sixthTdNode = root.SelectSingleNode("//table[1]/tr[last()]/td[6]");
If you wanted to mix it up even more you can try this:
HtmlNode nthTdNode = root.SelectSingleNode("//table[1]/tr[last()]/td[" + 6 + "]");

C# HtmlAgilityPack : startIndex cannot be larger than length of string

I'm trying to do something like this :
var document = htmlWeb.Load(searchUrl);
var hotels = document.DocumentNode.Descendants("div")
.Where(x => x.Attributes.Contains("class") &&
x.Attributes["class"].Value.Contains("listing-content"));
int count = 1;
foreach (var hotel in hotels)
{
HtmlDocument htmlDoc = new HtmlDocument();
htmlDoc.OptionFixNestedTags = true;
htmlDoc.Load(hotel.InnerText);
if (htmlDoc.DocumentNode != null)
{
var anchors = htmlDoc.DocumentNode.Descendants("div")
.Where(x => x.Attributes.Contains("class") &&
x.Attributes["class"].Value.Contains("srp-business-name")); // Error Occurring in here //
foreach (var anchor in anchors)
{
Console.WriteLine(anchor.InnerHtml);
}
}
}
I'm getting results like this :
New York Marriott Marquis
<span class="external-link">
<img height="15" src="/images/sprites/search/icon-link-external.png" width="16">
</span>
And
Courtyard by Marriott New York Manhattan/Times Square South
And so on.
Now I want the innerHtml of the anchors tags having class="url redbold mip-link". So I'm doing this :
var document = htmlWeb.Load(searchUrl);
var hotels = document.DocumentNode.Descendants("div")
.Where(x => x.Attributes.Contains("class") &&
x.Attributes["class"].Value.Contains("listing-content"));
int count = 1;
foreach (var hotel in hotels)
{
HtmlDocument htmlDoc = new HtmlDocument();
htmlDoc.OptionFixNestedTags = true;
htmlDoc.Load(hotel.InnerText);
if (htmlDoc.DocumentNode != null)
{
var anchors = htmlDoc.DocumentNode.Descendants("div")
.Where(x => x.Attributes.Contains("class") &&
x.Attributes["class"].Value.Contains("srp-business-name"));
foreach (var anchor in anchors)
{
htmlDoc.LoadHtml(anchor.InnerHtml);
var hoteltags = htmlDoc.DocumentNode.SelectNodes("//a");
foreach (var tag in hoteltags)
{
if (!string.IsNullOrEmpty(tag.InnerHtml) || !string.IsNullOrWhiteSpace(tag.InnerHtml))
{
Console.WriteLine(tag.InnerHtml);
}
}
}
}
}
I' getting the first result properly which is New York Marriott Marquis but in the second result an error occurring :
startIndex cannot be larger than length of string. What am I doing wrong ??
You are using the same DOM object for all your operations:
foreach (var hotel in hotels)
{
HtmlDocument htmlDoc = new HtmlDocument();
And after that you are using the same object for loading anchor tags:
foreach (var anchor in anchors)
{
htmlDoc.LoadHtml(anchor.InnerHtml);
Just change the document in the second iterator and it should work as expected.
foreach (var anchor in anchors)
{
var htmlDocAnchor= new HtmlDocument();
htmlDocAnchor.LoadHtml(anchor.InnerHtml);// And etc..

LINQ to XML Get (children?) of element?

How would I go about getting the ID information using Linq. I'm trying to add them to an array of int.
<FactionAttributes>
<name>Player</name>
<id>0</id>
<relationModifier>1</relationModifier>
<relations>
<id0>100</id0>
<id1>50</id1>
<id2>50</id2>
<id3>50</id3>
<id4>50</id4>
<id5>50</id5>
</relations>
</FactionAttributes>
That is my XML.
Here is the code I'm using so far.
void InitFactions()
{
int count = 0;
string filepath = Application.dataPath + "/Resources/factiondata.xml";
XDocument factionXML = XDocument.Load(filepath);
var factionNames = from factionName in factionXML.Root.Elements("FactionAttributes")
select new {
factionName_XML = (string)factionName.Element("name"),
factionID_XML = (int)factionName.Element("id"),
factionRelations_XML = factionName.Element("relations")// Need to turn this into array.
};
foreach ( var factionName in factionNames)
++count;
foreach ( var factionName in factionNames)
{
Factions f = new Factions();
f.otherFactionsName = new string[count];
f.otherFactionsRelation = new int[count];
int others = 0;
f.FactionName = factionName.factionName_XML;
Debug.Log(factionName.factionRelations_XML);
// Adds Rivals, not self to other list.
foreach (var factionName2 in factionNames)
{
if (factionName.factionID_XML == factionName2.factionID_XML)
continue;
f.otherFactionsName[(int)factionName2.factionID_XML] = factionName2.factionName_XML;
// THIS IS WHERE IM ADDING THE RELATIONS IN //
f.otherFactionsRelation[(int)factionName2.factionID_XML] = factionName.factionRelations_XML[(int)factionName2.factionID_XML];
Debug.Log(f.FactionName + " adds: " + factionName2.factionName_XML);
++others;
}
}
}
I have made multiple attempts using nodes and what not. I can't seem to figure out the correct syntax.
XDocument doc = XDocument.Load(Path);
//To get <id>
var MyIds = doc.Element("FactionAttributes").Element("id").Value;
//To get <id0>, <id1>, etc.
var result = doc.Element("FactionAttributes")
.Element("relations")
.Elements()
.Where(E => E.Name.ToString().Contains("id"))
.Select(E => new { IdName = E.Name, Value = E.Value});
If you want array of ints replace the select with this
.Select(E => Convert.ToInt32(E.Value)).ToArray();
If you are just after the relations Ids use this simple query
var doc = XDocument.Load("c:\\tmp\\test.xml");
var ids = doc.Descendants("relations").Elements().Select(x => x.Value);
If you want the Id and the relations ids in one array use this
var id = doc.Descendants("id").Select(x=>x.Value).Concat(doc.Descendants("relations").Elements().Select(x => x.Value));

Categories

Resources