I have a product structure table like the following:
<table>
<tr>
<td>Parent</td>
<td>Component</td>
<td>Quantity</td>
</tr>
<tr>
<td>123100A</td>
<td>123201B</td>
<td>1</td>
</tr>
<tr>
<td>123201B</td>
<td>123301A</td>
<td>1</td>
</tr>
<tr>
<td>123201B</td>
<td>123302A</td>
<td>1</td>
</tr>
<tr>
<td>123301A</td>
<td>123401A</td>
<td>1</td>
</tr>
<tr>
<td>123301A</td>
<td>123402A</td>
<td>1</td>
</tr>
<tr>
<td>123301A</td>
<td>123403A</td>
<td>1</td>
</tr>
</table>
Currently, I populate a list with my product structure and recursively loop through it to get all the base level components of a finished good item. The finished good item would be 123100A, or any parent that doesn't show up as a component in the list. In the end, I get a list that looks like this:
<table>
<tr>
<td>Parent</td>
<td>Component</td>
<td>Quantity</td>
</tr>
<tr>
<td>123100A</td>
<td>123302A</td>
<td>1</td>
</tr>
<tr>
<td>123100A</td>
<td>123401A</td>
<td>1</td>
</tr>
<tr>
<td>123100A</td>
<td>123402A</td>
<td>1</td>
</tr>
<tr>
<td>123100A</td>
<td>123403A</td>
<td>1</td>
</tr>
</table>
Here is the code I use to recursively loop to find each end component:
public void getCapacityComponents(string parPart, string partNum, decimal qtyMultiplier)
{
//Start of recursion to get child items
List<ProductStructure> capacity = new List<ProductStructure>();
var result = from x in psList
join y in partsList on x.parent equals y.part
where x.parent == partNum
select x;
//recursive loop through components
foreach (var x in result)
{
ProductStructure mrpProduct = new ProductStructure();
mrpProduct.parent = x.parent;
mrpProduct.component = x.component;
if (x.quantity == 0)
mrpProduct.quantity = qtyMultiplier;
else
mrpProduct.quantity = x.quantity * qtyMultiplier;
capacity.Add(mrpProduct);
}
if (capacity.Count > 0)
{
foreach (var part in capacity)
{
getCapacityComponents(parPart, part.component, part.quantity);
}
}
else
{
ProductStructure capacityPart = new ProductStructure();
capacityPart.parent = parPart;
capacityPart.component = partNum;
capacityPart.quantity = qtyMultiplier;
mrpProductList.Add(capacityPart);
}
//End of current solution to get child items
}
I send this function a list of finished good parts and use the MRPProductList to compare the components to all finished goods. I get the result I want but this takes a very long time to run. I usually have around 2700 Finished good parts that I need to loop through to get all end component items.
Is there a more efficient way to go through a list to find these items without doing the recursive loop?
Related
I know the Title says a lot, don't worry, I'll break it down for you.
Ok so I have one .txt file with the words - Horsemen - in it, called TeamName.txt
I have another 6 .txt files with HTML code which my code fetches and downloads - this is called Ladder-1-100.txt - NOW! The easy part:
Here's the idea, the code sifts through the HTML ladder.txt file for the team name, which my code does now fine. BUT, I want it to pull out other information too, whilst inside that specific #class. Not Specfic enough in my explaination? I'll show you.
<tr class="vrml_table_row">
<td class="pos_cell">59</td>
<td class="div_cell"><img src="/images/div_gold_40.png" title="Gold" /></td>
<td class="team_cell"><img src="/images/logos/teams/9b3b1917-a56b-40a3-80ee-52b1c9f31910.png" class="team_logo" /><span class="team_name">Echoholics</span></td>
<td class="group_cell"><img src="/images/group_ame.png" class="group_logo" title="America East" /></td>
<td class="gp_cell">14</td>
<td class="win_cell">10</td>
<td class="loss_cell">4</td>
<td class="pts_cell">340</td>
<td class="mmr_cell"><span>1200</span></td>
</tr>
<tr class="vrml_table_row">
<td class="pos_cell">60</td>
<td class="div_cell"><img src="/images/div_diamond_40.png" title="Diamond" /></td>
<td class="team_cell"><img src="/images/logos/teams/dff8310a-a429-4c60-af82-0333d530d22d.png" class="team_logo" /><span class="team_name">Horsemen</span></td>
<td class="group_cell"><img src="/images/group_aa.png" class="group_logo" title="Oceania/Asia" /></td>
<td class="gp_cell">10</td>
<td class="win_cell">6</td>
<td class="loss_cell">4</td>
<td class="pts_cell">235</td>
<td class="mmr_cell"><span>1200</span></td>
</tr>
<tr class="vrml_table_row">
<td class="pos_cell">61</td>
<td class="div_cell"><img src="/images/div_gold_40.png" title="Gold" /></td>
<td class="team_cell"><img src="/images/logos/teams/8eb6109e-f765-4d64-a766-cc5605a01ad0.png" class="team_logo" /><span class="team_name">Femboys</span></td>
<td class="group_cell"><img src="/images/group_ame.png" class="group_logo" title="America East" /></td>
<td class="gp_cell">12</td>
<td class="win_cell">8</td>
<td class="loss_cell">4</td>
<td class="pts_cell">348</td>
<td class="mmr_cell"><span>1200</span></td>
</tr>
Here is my current code that will spit out: Team Name: Horsemen.
HtmlNode[] team_name = document1.DocumentNode
.SelectSingleNode("//*[#class='vrml_table_row']")
.SelectNodes("//td[#class='team_cell']")
.Where(x => x.InnerHtml.Contains($"{TeamName}"))
.ToArray();
foreach (HtmlNode item in team_name)
{
await ReplyAsync("**Team Name:** " + item.InnerHtml);
}
However, I want it to spit out:
Team Name: Horsemen, Wins: 6, Losses: 4, Games Played: 10, MMR: 1200, Points Scored: 235, Division: Diamond, Ladder Position: 60.
You get my point. As you can see, each of those classes are labeled the same, expect for their information inside. By the way, the Team Name - Horsemen - is Dynamic, meaning it can be replaced with another team name. So how do I acheive this?
A sample solution would be this one:
Firstly create a Model class
class Model
{
public int Position { get; set; }
public string TeamName { get; set; }
public string ImageSource { get; set; }
public string Division { get; set; }
//whatever you want to store
}
After that should keep the desired nodes in HtmlNodeCollection and our model in a List :
var table = htmlDoc.DocumentNode.SelectNodes("//tr[contains(#class, 'vrml_table_row')]");
var models = new List<Model>();
foreach (var t in table)
{
var model = new Model
{
//I used the first 8 columns of the desired table
Position = int.Parse(t.SelectSingleNode("td[contains(#class, 'pos_cell')]").InnerText),
ImageSource = t.SelectSingleNode("td[contains(#class, 'div_cell')]/img").Attributes["src"].Value,
Division = t.SelectSingleNode("td[contains(#class, 'div_cell')]/img").Attributes["title"].Value,
TeamLink = t.SelectSingleNode("td[contains(#class, 'team_cell')]/a").Attributes["href"].Value,
TeamLogo = t.SelectSingleNode("td[contains(#class, 'team_cell')]/a/img").Attributes["src"].Value,
TeamName = t.SelectSingleNode("td/a/span[contains(#class, 'team_name')]").InnerText,
GroupLogo = t.SelectSingleNode("td[contains(#class, 'group_cell')]/img").Attributes["src"].Value,
GroupTitle = t.SelectSingleNode("td[contains(#class, 'group_cell')]/img").Attributes["title"].Value
// etc
};
models.Add(model);
}
I have a table in the HTML code below:
<table style="padding: 0px; border-collapse: collapse;">
<tr>
<td><h3>My Regional Financial Office</h3></td>
</tr>
<tr>
<td> </td>
</tr>
<tr>
<td><h3>My Address</h3></td>
</tr>
<tr>
<td>000 Test Ave S Ste 000</td>
</tr>
<tr>
<td>Golden Valley, MN 00000</td>
</tr>
<tr>
<td>Get Directions</td>
</tr>
<tr>
<td> </td>
</tr>
</table>
How can I get the inner text of the next 2 <tr> tags after the tablerow containing the text "My Address?"
You can use following XPath :
var htmlDoc = new HtmlDocument();
htmlDoc.LoadHtml(html);
var tdOfInterests =
htmlDoc.DocumentNode
.SelectNodes("//tr[td/h3[.='My Address']]/following-sibling::tr[position() <= 2]/td");
foreach (HtmlNode td in tdOfInterests)
{
//given html input in question following code will print following 2 lines:
//000 Test Ave S Ste 000
//Golden Valley, MN 00000
Console.WriteLine(td.InnerText);
}
The key of above XPath is using following-sibling with position() filter.
UPDATE :
A bit explanation about the XPath used in this answer :
//tr[td/h3[.='My Address']]
above part select <tr> element that has :
child <td> element that has child <h3> element with value equals
'My Address'
/following-sibling::tr[position() <= 2]
next part select following <tr> element with position <=2 from current <tr> element (the one selected by previous XPath part)
/td
the last part select child <td> element from current <tr> element
I trying to change value of a particular cell in a table, but i am getting an error, can anyone see what the problem is please :
Test WebTable.IWebTableTests.testIWebTableTests failed: System.NullReferenceException : Object reference not set to an instance of an object.
WebTableTests.cs(37,0): at WebTable.IWebTableTests.testIWebTableTests()
<div class="cart-info">
<table border="1">
<thead>
<tr>
<td class="name">Product Name</td>
<td class="model">Model</td>
<td class="quantity">Quantity</td>
<td class="price">Unit Price</td>
<td class="total">Total</td>
</tr>
</thead>
<tbody>
</table>
</div>
and:
IWebElement table = driver.FindElement(By.CssSelector(".cart-info>table"));
ReadOnlyCollection<IWebElement> allRows = table.FindElements(By.TagName("tr"));
ReadOnlyCollection<IWebElement> allCols = table.FindElements(By.TagName("td"));
//Verify that it has three rows
Assert.AreEqual(3, allRows.Count);
//Verify that it has six columns
Assert.AreEqual(5, allCols.Count);
//Verify that specified value exists in second cell of third row
Assert.AreEqual("iPhone", allRows[3].FindElements(By.TagName("td"))[1].Text);
//Get in cell editor and enter some value
string cellValue = allRows[3].FindElements(By.TagName("td"))[3].Text;
IWebElement cellEdit = allRows[3].FindElements(By.TagName("td"))[3];
cellEdit.Clear();
cellEdit.SendKeys("2");
string aftercellValue = allRows[3].FindElements(By.TagName("td"))[3].Text;
I want to fetch all rows having a specific word/string in its.. and store it in array
I have a string as below
<tr>
<td>Total</td>
<td>123</td>
<td>567</td>
</tr>
<tr>
<td>ABC</td>
<td>123</td>
<td>567</td>
</tr>
<tr>
<td>XYZ</td>
<td>123</td>
<td>567</td>
</tr>
<tr>
<td>Total</td>
<td>7676</td>
<td>8767</td>
</tr>
I want to fetch a row having the string Total and the value of should store in array
So output should
<tr>
<td>Total</td>
<td>123</td>
<td>567</td>
</tr>
<tr>
<td>Total</td>
<td>7676</td>
<td>8767</td>
</tr>
what should be the regular expression to fetch a row with a string "Total"
To build arrays for each table row that has a cell with the word "Total", you could use this regex:
(?<=<tr>\s*<td>Total</td>)(\s*<td>\d+</td>)+(?=\s*</tr>)
Which would give you the following 2 matches:
<td>123</td>
<td>567</td>
and
<td>7676</td>
<td>8767</td>
On these matches you could then split with this regex to get arrays in return:
\D+
IN JQUERY UR SOLUTION WILL--->
var tbl = $('#tblId')
var array = [];
$('tr td' ,tbl).each(function(){
var htmlstring = (this).innerHTML;
if(htmlstring == 'Total')
{
if((this).innerHTML == 'Total')
{
$('td', this.parentNode).each(function(){
array.push(this);
});
}
}
});
alert(array);
http://jsfiddle.net/gXGj6/13/
Good solution using jQuery:
http://jsfiddle.net/robfarmer/KaGBL/2/
HTML:
Source
<table id="source">
<tr>
<td>Total</td>
<td>123</td>
<td>567</td>
</tr>
<tr>
<td>ABC</td>
<td>123</td>
<td>567</td>
</tr>
<tr>
<td>XYZ</td>
<td>123</td>
<td>567</td>
</tr>
<tr>
<td>Total</td>
<td>7676</td>
<td>8767</td>
</tr>
</table>
Results
<table id="results"></table>
Array Results:
<ul id="arrayResults"/>
Javascript
$(document).ready(function() {
$("#source tr td:contains('Total')").closest("tr").clone().appendTo("#results");
var cells = [];
$("#source tr td:contains('Total')").closest("tr")
.children("td").not(":contains('Total')").each(function(index, element) {
cells.push($(element).text());
});
$(cells).each(function(index, element) {
$("#arrayResults").append($("<li>").text(element));
});
});
I'm trying to parse some HTML using the HTML Agility Pack. The following code snippet selects the table element containing the information I need but I need to dig deeper into the table.
Once I have the InnerHtml of the table, I plan to look for a <td> with an innertext value of "Field #2", for example. But, then, I need to select the innertext of the NEXT <td>. I need the value 110, in this example. How do I do that?
foreach (var x in doc.DocumentNode.SelectNodes("//table[contains(#class,'data')]"))
{
// psuedo code - search for td and use "contains" on the inner text / html.
// Then, grab the next td inner html.
Console.WriteLine(x.InnerHtml);
}
<tr>
<td width="158"><strong>Field #1:</strong></td>
<td width="99">1</td>
<td width="119"><strong>Field #2:</strong></td>
<td width="176">110</td>
</tr>
<tr>
<td width="158"><strong>Field #3:</strong></td>
<td width="99">85</td>
<td width="119"><strong>Field #4:</strong></td>
<td width="176">-259.34</td>
</tr>
<tr>
<td width="158"><strong>Field #5:</strong></td>
<td width="99">1</td>
<td width="119"><strong>Field #6:</strong></td>
<td width="176">110</td>
</tr>
<tr>
<td width="158"><strong>Field #7:</strong></td>
<td width="99">12</td>
<td width="119"><strong>Field #8:</strong></td>
<td width="176">123.23</td>
</tr>
This piece of code will return you desired td row.
//<td width="176">110</td>
var td = x.SelectNodes("//td").SkipWhile(g => !g.InnerText.Contains("Field #2:")).Select(s => s).Skip(1).FirstOrDefault();
Not sure the agility pack supports it, but in XPath you can query for the next sibling by using /following-sibling:
doc.DocumentNode.SelectNodes(
"//table[contains(#class,'data')]/tr/" +
"td[/strong/text()='Field #2:']" +
"/following-sibling:td");
essentially - find all of the td nodes with the given text, and give me it's next sibling td node.