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
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.
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
}
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 + "]");
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..
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));