I have HTML Code in a string named gridHTML
<html>
<body>
<style>a{text-decoration:none; color: black;} th { border: solid thin; }
td{text-align: center;vertical-align: middle;font-family: Arial;font-size: 8pt; height: 50px;
border-width: 1px;border-left-style: solid;border-right-style: solid;}
table { border-collapse: collapse; } tr:nth-child(1) { border: solid thin; border-width: 2px;}
tr{ border: solid thin; border-style: dashed solid dashed solid;}
</style>
<div>
<table >
<tr class='leftColumnTableHeadO' align='center' style='font-family: Arial; font-size: 8pt; font-weight: normal; width: 100px;'>
<th scope='col'>TM No.</th>
<th scope='col' style='width: 83px;'>Filing Date</th>
<th scope='col'>TradeMark</th>
<th scope='col'>Class</th>
<th scope='col'>Jr#</th>
<th scope='col'>Applicant</th>
<th scope='col'>Agent / Attorney</th>
<th scope='col'>Status</th>
<th scope='col'>City</th>
<th scope='col'>Logo</th>
</tr>
<tr class='lightGrayBg' >
<td ><a title='View Report' class='calBtn' href='javascript:__doPostBack('ctl00$MainContent$grdTradeMarkNumber$ctl02$ctl00','')'>38255</a> </td>
<td ><span id='MainContent_grdTradeMarkNumber_lblFilingDate_0'>09-12-1962</span> </td>
<td >IMIDAN</td>
<td >5</td>
<td >158</td>
<td >test</td>
<td >test</td>
<td >Registered</td>
<td >DELWARE</td>
<td ></td>
</tr>
<tr >
<td ><a title='View Report' class='calBtn' href='javascript:__doPostBack('ctl00$MainContent$grdTradeMarkNumber$ctl03$ctl00','')'>188389</a> </td>
<td ><span id='MainContent_grdTradeMarkNumber_lblFilingDate_1'>09-09-2003</span> </td>
<td >RAND</td>
<td >16</td>
<td >682</td>
<td >Ttest </td>
<td >test </td>
<td >Advertised</td>
<td >CALIFORNIA</td>
<td ></td>
</tr>
<tr class='lightGrayBg' >
<td ><a title='View Report' class='calBtn' href='javascript:__doPostBack('ctl00$MainContent$grdTradeMarkNumber$ctl04$ctl00','')'>207063</a> </td>
<td ><span id='MainContent_grdTradeMarkNumber_lblFilingDate_2'>11-03-2005</span> </td>
<td >FP DIESEL</td>
<td >7</td>
<td >690</td>
<td >testtest</td>
<td >testtest</td>
<td >Advertised</td>
<td >-</td>
<td ></td>
</tr>
</table>
</div>
</body>
</html>
I want to get all rows separately in a list
i am using split method to do this
List<string> rows = gridHTML.Split(new string[] { "<tr" }, StringSplitOptions.None).ToList();
but the problem is when i look into the list "<td" is removed
Is there any (other) way to get all rows in a list ?
For this one, you could use Linq To XML easily. ie:
var rows = XElement.Parse(gridHTML).Descendants("tr");
var cells = rows.Elements("td");
var cellContentsAsString = cells.Select(c => (string)c);
etc.
You should not use string methods (or regex) to parse HTML, i recommend HtmlAgilityPack:
var doc = new HtmlAgilityPack.HtmlDocument();
doc.LoadHtml(gridHTML);
List<HtmlNode> trList = doc.DocumentNode.Descendants("tr").ToList();
Since it seems that you want to load this table data into a collection, maybe following approach is better for your requirement. It will load the rows and cells into a DataTable, even the DataColumns are initialized correctly with the table-header values:
DataTable table = new DataTable();
bool firstRowContainsHeader = true;
var tableRows = doc.DocumentNode.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);
}
}
Related
I'm trying to make a calendar table which uses a condition to jump to next row everytime (DayOfTheWeek = Sunday), but i cant use <tr> because Google Chrome doesn't assimilate it.
Sorry cant include other parts of the code, but its confidential.
#*Html Part *#
<table class="table table-bordered">
<tr style="background-color:black">
<td align="center" style="color:white">Lunes</td>
<td align="center" style="color:white">Martes</td>
<td align="center" style="color:white">Miercoles</td>
<td align="center" style="color:white">Jueves</td>
<td align="center" style="color:white">Viernes</td>
<td align="center" style="color:white">Sabado</td>
<td align="center" style="color:white">Domingo</td>
</tr>
<tbody>
#for (int a = 1; a < dayOfWeekFirst; a++)
{
<td align="center"> </td>
}
#for (int i = 1; i <= daysInCurrentMonth; i++)
{
DateTime renderedDay = new DateTime(firstDay.Year, firstDay.Month, i);
<td align="center">#i</td>
if (renderedDay.DayOfWeek == DayOfWeek.Sunday)
{
//// Next Row
<tr />
}
}
#for (int a = 1; a <= 7 - dayOfWeekLast; a++)
{
<td align="center"> </td>
}
</tbody>
</table>
I don't believe the <tr /> is allowed as a row is expected to have cell elements.
Try adding an empty cell.
if (renderedDay.DayOfWeek == DayOfWeek.Sunday)
{
//// Next Row
<tr><td> </td></tr>
}
EDIT, then try closing the element with a closing tag. The tr element is not void-element in HTML so you shouldn't use <tr />.
if (renderedDay.DayOfWeek == DayOfWeek.Sunday)
{
//// Next Row
<tr></tr>
}
I am having trouble dealing with a dynamic table.
This is our table:
<table class="table" style="min-width: 870px; max-width: 870px">
<colgroup>
<col style="width: 30px">
<col style="width: 200px">
<col style="width: 80px">
<col style="width: 70px">
<col style="width: 200px">
<col style="width: 50px">
<col style="width: 50px">
</colgroup>
<tbody>
<tr></tr>
<tr></tr>
<tr></tr>
<tr></tr>
<tr></tr>
<tr></tr>
<tr></tr>
</tbody>
<tfoot>
<tr>
<td class="text-right" colspan="3">Media del grupo</td>
<td class="text-center media" colspan="1">1</td>
<td class="text-center noeditable" colspan="1"></td>
<td class="text-center media" colspan="1"></td>
<td class="text-center media" colspan="1"></td>
</tr>
</tfoot>
</table>
Each <tr> contains the following:
<tr>
<td class="indice">1</td>
<td id="accion-1-alumno-0" data-tooltip="" class="has-tip titulo" title="">Ap_Alumno_1ESOA_1, Nb_Alumno_1ESOA_1</td>
<td data-tooltip="" class="has-tip titulo" data-selector="tooltipdtk00g" title="">1ESOA</td>
<td class="nota relative " style="text-align:center; color: #ed1c24!important">
<div id="accion-1-celda-0-0-0" class="elemento comentarios">1</div>
</td>
<td class="nota relative " style="text-align:center; color: #000000!important">
<div class="elemento comentarios"><span id="accion-1-editar-1-0" class="block left ellipsis span comentario" title=""></span><span id="accion-1-prismaticos-1-0" class="glyphicons glyph_observaciones observacion right"></span></div>
</td>
<td class="nota relative " style="text-align:center; color: #000000!important">
<div id="accion-1-celda-2-0-0" class="elemento comentarios"></div>
</td>
<td class="nota relative " style="text-align:center; color: #000000!important">
<div id="accion-1-celda-3-0-0" class="elemento comentarios"></div>
</td>
</tr>
We are interested in the elements
<div id="accion-1-celda-0-0-0" class="elemento comentarios">1</div>
which are being added to a IList<IWebElement>
However, when trying to SendKeys to the element, the first time it will work correctly, however the second time will always fail with StaleElementReferenceException, this is because the previous element (the first one) has changed and with it the page DOM has also changed.
I am trying to find a way to find the element again if StaleElementReferenceException is thrown.
So far, both this methods have failed:
Method one
public virtual void Introducir_NotasAlumnos(string nota)
{
IList<IWebElement> divNota = tablaNotas
.Select((element, index) => element.FindElement(By.Id("accion-1-celda-0-" + index + "-0")))
.ToList();
divNota.ToList().ForEach(element => Introducir_Nota(element, nota));
}
Method two
public virtual void Introducir_NotasAlumnos(string nota)
{
int index = 0;
foreach (IWebElement element in tablaNotas)
{
By locator = By.Id("accion-1-celda-0-" + index + "-0");
Introducir_Nota(element.FindElement(locator), nota);
index++;
}
}
Thanks for your time.
Here your locators:
table: .table tbody > tr
table row by index: .table tbody > tr:nth-child(1)
and you method (java code):
int size = driver.findElements(By.cssSelector(".table tbody > tr")).size();
for (int i = 0; i < size; i++) {
WebElement row = driver.findElement(By.cssSelector(".table tbody > tr:nth-child(" + i + ")"));
By locator = By.id("accion-1-celda-0-" + i + "-0");
Introducir_Nota(row.findElement(locator), nota);
}
You have certain count of rows and you find row element independently, should not throw StaleElementReferenceException exception.
Here shorter version:
int size = driver.findElements(By.cssSelector(".table tbody > tr")).size();
for (int i = 0; i < size; i++) {
Introducir_Nota(row.findElement(By.cssSelector("#accion-1-celda-0-" + i + "-0")), nota);
}
I have this table.
<tr>
<td style="padding-left: 25pt;"><font style="background-color: white" color="black"> Hello</font></td>
<td style="padding-left: 25pt;"><font style="background-color: white" color="black">Bye</font></td>
</tr>
but I want to add an extra td element at the end so it looks like this:
<tr>
<td style="padding-left: 25pt;"><font style="background-color: white" color="black"> Hello</font></td>
<td style="padding-left: 25pt;"><font style="background-color: white" color="black">Bye</font></td>
<td>1</td>
</tr>
I am using htmlAgilityPack, but the examples online that I have looked don't exactly help.
i hope this may help you
string data = #"<tr><td style='padding-left: 25pt;'><font style='background-color: white' color='black'> Hello</font></td><td style='padding-left: 25pt;'><font style='background-color: white' color='black'>Bye</font></td></tr>";
string rowToAppend = "<td>1</td>";
var html = new HtmlAgilityPack.HtmlDocument();
html.LoadHtml(data);
var table = html.DocumentNode.SelectNodes("tr").FirstOrDefault();
var node = HtmlNode.CreateNode(rowToAppend);
table.AppendChild(node);
data += table.OuterHtml;
I have a table:
<table id="trTable" runat="server" clientidmode="Static">
<thead>
<tr>
<th style="display:none">
ID
</th>
<th style="width: 112px">
Item
</th>
<th style="width: 40px; text-align: left">
Price
</th>
<th style="width: 24px; text-align: center">
</th>
<th style="width: 26px; text-align: center">
Qty
</th>
<th style="width: 24px; text-align: center">
</th>
<th style="width: 40px; text-align: right">
Total
</th>
</tr>
</thead>
<tbody>
</tbody>
</table>
and new rows are added to it with jQuery:
var newRow = $("<tr> <td class='drinkID' style='display:none'>" + drinkID + "</td> <td class='drinkName'>" + dName + "</td> <td class='drinkPrice'>" + dPrice + "</td> <td style='text-align:center'><input id='Button' type='button' value='<' class='minusButton' /> </td> <td class='drinkQty'>1</td> <td style='text-align:center'><input id='Button' type='button' value='>' class=\"plusButton\" /></td> <td class='drinkTotal'>" + dPrice + "</td> </tr>");
How do I access the content of the cells using asp.net?
I am using:
foreach (HtmlTableRow row in trTable.Rows)
{
Response.Write("RowDetails:" + row.Cells[1].InnerHtml);
}
But the response.write just outputs:
RowDetails: Item
How come it doesn't get the cell contents?
What you change on the html struct page, on client side, is not send back on the server, and sever know nothing about.
With other words, what is on the page, is not fully sanded back on the server.
To solve this, you can make at the same time two edits, one on what user see and one hidden on a hidden input, to post back to the server the changes and recreate the table on the server side.
Hope this make scene.
You can also use Microsoft Ajax enabling partial rendering on in the row. This will do the same postback effect but will only send the afffected content to the client side.
<td valign="top" class="m92_h_bigimg">
<img border=0 src="http://i2.giatamedia.de/s.php?uid=168846&source=xml&size=320&vea=5vf&cid=2492&file=007399_8790757.jpg" name="bigpic">
</td>
<td valign="top" class="m92_h_bigimg2">
<table border=0 cellpadding=0 cellspacing=0>
<tr>
<td valign="top" class="m92_h_para">Hotel:</td>
<td valign="top" class="m92_h_name">
Melia Tropical <br>
<img src="/images/star.gif" height=13 width=13 alt="*"><img src="/images/star.gif" height=13 width=13 alt="*"><img src="/images/star.gif" height=13 width=13 alt="*"><img src="/images/star.gif" height=13 width=13 alt="*"><img src="/images/star.gif" height=13 width=13 alt="*">
</td>
</tr>
<tr>
<td valign="top" class="m92_h_para">Zimmer:</td>
<td valign="top" class="m92_h_wert"><b>Suite</b></td>
</tr>
<tr>
<td valign="top" class="m92_h_para">Verpflegung:</td>
<td valign="top" class="m92_h_wert"><b>All Inclusive</b></td>
</tr>
<tr>
<td valign="top" class="m92_h_para">Ort:</td>
<td valign="top" class="m92_h_wert">Punta Cana</td>
</tr>
<tr>
<td valign="top" class="m92_h_para">Region:</td>
<td valign="top" class="m92_h_wert">Punta Cana</td>
</tr>
<tr>
<td valign="top" class="m92_h_para">Land:</td>
<td valign="top" class="m92_h_wert">Dom. Republik</td>
</tr>
<tr>
<td valign="top" class="m92_h_para">Anbieter:</td>
<td valign="top" class="m92_h_wert"><img border=0 src="http://www.lmweb.net/lmi/va/gifs/5VF.gif" alt="5 vor Flug" title="5 vor Flug"><br>5 vor Flug</td>
</tr>
</table>
<table border=0 cellpadding=0 cellspacing=0>
<tr>
<td><img src="/images/dropleftw.gif" height="16" width="18"></td>
<td>
<div id="mark" class="m92_notice">
<a target="vakanz" href="siteplus/reminder.php?session_id=rslr1ejntpmj07n0f2smqfhsj5&REC=147203&m_flag=1&m_typ=hotel">Dieses Hotel merken</a>
</div>
</td>
</tr>
<tr>
<td><img src="/images/dropleftw.gif" height="16" width="18"></td>
<td>
<div class="m92_notice">
Hotelbewertung anzeigen
</div>
</td>
</tr>
</table>
</td>
With the HtmlAgility-pack, how can I get the data between <td valign="top" class="m92_h_bigimg"> and his closing <td>. I tried with this code not using the HtmlAgility-pack and this works but it found first </td> and closed. So the code is not correct. I read that the HtmlAgility-pack is the best solution for this kind of problems.
public static string[] GetStringInBetween(string strBegin, string strEnd, string strSource, bool includeBegin, bool includeEnd)
{
string[] result = { "", "" };
int iIndexOfBegin = strSource.IndexOf(strBegin, StringComparison.Ordinal);
if (iIndexOfBegin != -1)
{
int iEnd = strSource.IndexOf(strEnd, iIndexOfBegin, StringComparison.Ordinal);
if (iEnd != -1)
{
result[0] = strSource.Substring(iIndexOfBegin + (includeBegin ? 0 : strBegin.Length), iEnd + (includeEnd ? strEnd.Length : 0) - iIndexOfBegin);
if (iEnd + strEnd.Length < strSource.Length)
result[1] = strSource.Substring(iEnd + strEnd.Length);
}
}
return result;
}
How can I do this?
HtmlAgilityPack.HtmlDocument htmlDoc = new HtmlAgilityPack.HtmlDocument();
htmlDoc.LoadHtml(html);
var str = htmlDoc.DocumentNode
.Descendants("td")
.Where(x => x.Attributes["class"] != null && x.Attributes["class"].Value == "m92_h_bigimg")
.Select(x => x.InnerHtml)
.First();
The HtmlAgilityPack supports standard XPath queries, so I think you could do something like:
foreach (var node in doc.DocumentElement.SelectNodes("//td[#class='m92_h_bigimg']"))
{
// Do work on your node.
}
... where doc is your instance of HtmlDocument