0

I am developing a C# application in which I need to parse a specific row from a table and compare its different values to a given string.

The URL I want to parse is http://wsrpg.com/clans/57

<table cellspacing="0" cellpadding="0" border="0" class="table">
<thead>
<tr>
<th width="100">Rank</th>
<th width="150">Nick</th>
<th width="100">RCASH</th>
<th width="150">Activity in December</th>
<th width="100">Comportment</th>
<th width="100">Online</th>
<th width="150">Last Login</th> 
</tr>
</thead>

<tr><td>Leader</td><td>robbie_william</td><td>351</td><td>1024</td><td>1195</td><td class='offline'><span class="label label-danger">Offline</span></td><td>03/01/2016</td></tr><tr><td>Boss</td><td>Alloy_</td><td>1418</td><td>1043</td><td>354</td><td class='offline'><span class="label label-danger">Offline</span></td><td>26/12/2015</td></tr><tr><td>Boss</td><td>AnonYmous_</td><td>32976</td><td>5142</td><td>937</td><td class='offline'><span class="label label-danger">Offline</span></td><td>04/01/2016</td></tr><tr><td>Boss</td><td>dJones</td><td>2739</td><td>6152</td><td>1044</td><td class='online'><span class="label label-success">Online</span></td><td>04/01/2016</td></tr><tr><td>Boss</td><td>SHARP</td><td>9015</td><td>1216</td><td>32</td><td class='offline'><span class="label label-danger">Offline</span></td><td>04/01/2016</td></tr><tr><td>Boss</td><td>Steffie</td><td>7888</td><td>6043</td><td>887</td><td class='online'><span class="label label-success">Online</span></td><td>04/01/2016</td></tr><tr><td>Boss</td><td>YOLOvsYODO</td><td>10950</td><td>2703</td><td>385</td><td class='offline'><span class="label label-danger">Offline</span></td><td>04/01/2016</td></tr><tr><td>Member</td><td>Angel_</td><td>8629</td><td>3256</td><td>167</td><td class='offline'><span class="label label-danger">Offline</span></td><td>04/01/2016</td></tr><tr><td>Member</td><td>asad</td><td>2452</td><td>3938</td><td>183</td><td class='offline'><span class="label label-danger">Offline</span></td><td>03/01/2016</td></tr><tr><td>Member</td><td>D3nim</td><td>1285</td><td>3217</td><td>31</td><td class='offline'><span class="label label-danger">Offline</span></td><td>03/01/2016</td></tr><tr><td>Member</td><td>Dell</td><td>5025</td><td>3305</td><td>182</td><td class='offline'><span class="label label-danger">Offline</span></td><td>01/01/2016</td></tr><tr><td>Member</td><td>Habib</td><td>1650</td><td>3860</td><td>36</td><td class='offline'><span class="label label-danger">Offline</span></td><td>04/01/2016</td></tr><tr><td>Member</td><td>Iron_MiXx</td><td>2569</td><td>485</td><td>525</td><td class='offline'><span class="label label-danger">Offline</span></td><td>03/01/2016</td></tr><tr><td>Member</td><td>MCool</td><td>4960</td><td>12739</td><td>290</td><td class='online'><span class="label label-success">Online</span></td><td>04/01/2016</td></tr><tr><td>Member</td><td>PREXEN</td><td>127</td><td>3873</td><td>1547</td><td class='offline'><span class="label label-danger">Offline</span></td><td>04/01/2016</td></tr><tr><td>Member</td><td>Sensation_</td><td>2733</td><td>1944</td><td>338</td><td class='offline'><span class="label label-danger">Offline</span></td><td>03/01/2016</td></tr><tr><td>Member</td><td>Wizard_</td><td>2081</td><td>2578</td><td>46</td><td class='offline'><span class="label label-danger">Offline</span></td><td>03/01/2016</td></tr>
</table>

I only want the nick's to be stored in a string or a string array, so that I can use it compare to an already given string.

What I want to achieve, is to check whether the nick entered by the user exists in this table or not.

I am going to use a bool method to achieve that.

Solution: I used Tim Schmelter's code, and here is how I used it:

private bool Authenticate(string nick)
        {
            using (WebClient client = new WebClient())
            {
                string html = client.DownloadString("http://wsrpg.com/clans/57");
                DataTable table = GetTable(html, "table", true);
                string[] nicks = table.AsEnumerable().Select(r => r.Field<string>("nick")).ToArray();
               if(nicks.Contains(nick))
                {
                    return true;
                }
               else
                {
                    return false;
                }
            }
        }

And then called it by

bool Authenticated = Authenticate(Player.GetName());
1
  • 1
    I'm just missing your own effort. Commented Jan 4, 2016 at 12:25

2 Answers 2

1

You could use this method that parses HTML and fills a DataTable with the first table that contains a given class name:

public static DataTable GetTable(string html, string tableClass, bool firstRowContainsHeader = false)
{
    var doc = new HtmlAgilityPack.HtmlDocument();
    doc.LoadHtml(html);

    string xpath = string.Format("//table[contains(@class,'{0}')]", tableClass);
    var firstTable = doc.DocumentNode.SelectSingleNode(xpath);
    if (firstTable == null) return null;

    DataTable table = new DataTable();
    var tableRows = firstTable.Descendants("tr");
    var tableData = tableRows.Skip(firstRowContainsHeader ? 1 : 0)
        .Select(row => row.Descendants("td")
            .Select((cell, index) => new { row, cell, index, cell.InnerText })
            .ToList());

    var headerCells = tableRows.First().Descendants()
        .Where(n => n.Name == "td" || n.Name == "th");
    int columnIndex = 0;
    foreach (HtmlNode cell in headerCells)
    {
        string colName = firstRowContainsHeader
            ? cell.InnerText
            : String.Format("Column {0}", (++columnIndex).ToString());
        table.Columns.Add(colName, typeof(string));
    }
    foreach (var rowCells in tableData)
    {
        DataRow row = table.Rows.Add();
        for (int i = 0; i < Math.Min(rowCells.Count, table.Columns.Count); i++)
        {
            row.SetField(i, rowCells[i].InnerText);
        }
    }

    return table;
}

Then you can use LINQ-To-DataTable to check if it contains the given nick:

string html = File.ReadAllText("C:\\Temp\\html.txt");  // loading your sample from file
DataTable table = GetTable(html, "table", true);
string nick = "robbie_william";  // input example
bool isContained = table.AsEnumerable()
    .Any(r => nick.Equals(r.Field<string>("nick"), StringComparison.InvariantCultureIgnoreCase));

if you just want to fill a string[] or List<string>:

string[] nicks = table.AsEnumerable().Select(r => r.Field<string>("nick")).ToArray(); // or ToList()
Sign up to request clarification or add additional context in comments.

5 Comments

Thank You, this worked. Question edited with solution
@HaiderAli: note that i've already shown how you can check it case insensitively. Your Contains approach would not find Robbie_William. If you have already the string[] you could also use the overload with a StringComparer: nicks.Contains(nick, StringComparer.InvariantCultureIgnoreCase);
i need your help again, i want to fetch the rank & offline/online status also of a given player, from the same page. Please help
@HaiderAli: then ask a complete question and i'll try to answer. You can add a link to the question here.
I am not allowed since a few of my questions have low reputation
1

Easiest way to do this is with the XPath of the element so from an application I have that parses a different table I have:

string tableResult = htmlDocument.DocumentNode.SelectSingleNode("//table[@class='output']/tr[3]/td[3]").InnerText;

1 Comment

I just used this and it was so much easier. Thank you.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.