To create xpath for html table to access desired record using 3 inputs - html

This is a structure of very basic html table. I want to create xpath for following scenario.
I will insert 2 field names like 'Name' and 'Salary' along with value of 'Name' field (say for example 'STU') then output should be 25k.
I was given hint like
string (xpath which will have 2 field names and one value) output of this function will be that key.
<html>
<body>
<h3>MY TABLE</h3>
<table>
<tbody>
<tr>
<th>id</th>
<th>Name</th>
<th>date</th>
<th>Address</th>
<th>salary</th>
</tr>
<tr>
<td>XYZ</td>
<td>STU</td>
<td>12/20/2015</td>
<td>Mumbai</td>
<td>25k</td>
</tr>
<tr><td>PQR</td>
<td>ABC</td>
<td>01/05/2015</td>
<td>Chennai</td>
<td>25k</td>
</tr>
<tr>
<td>ABC</td>
<td>PQR</td>
<td>03/09/2015</td>
<td>Bangalore</td>
<td>20k</td>
</tr>
<tr>
<td>emp4</td>
<td>XYZ</td>
<td>08/12/2015</td>
<td>Delhi</td>
<td>30k</td>
</tr>
</tbody>
</table>
</body>
</html>

Basics:
The first thing you will need to do is find which column(s) in the table contain(s) the field(s) you are searching for.
For example, to find the position of the Name column:
count(//tbody/tr/th[./text() = 'Name']/preceding-sibling::th) + 1
The above will return 2. (Of course, this technique won't necessarily work well if there are colspan attributes used in the HTML, but there are none in your example.)
Then, you can find the rows that contain a specific value in this column - for example STU - in this column like this:
//tbody/tr/td[position() = $WherePosition][./text() = 'STU']/..
Notice the use of the variable $WherePosition above. Here, I have used it to represent the result of the previous query (1). Depending on what tool you are using to perform the XPath query, you may or may not have the option to set variables. If you wish to use a single XPath expression or you don't want to or can't use variables, you can simply replace it with the previous XPath expression, although it will become less readable.
It's worth noting that aside from readability, variables will also make it easier to re-use the same expression, because you can, for example, substitute 'Name' in the first query for $WhereField, if you tell the XPath evaluator that you want to set the $WhereField variable to Name. And in the query to find the specific row (2), you can substitute 'STU' for $WhereValue, if you also set this variable accordingly.
Apply it:
Now to get the position of the salary column. If you used my tip above about using variables, you could re-execute the same expression as (1) again, but with the $WhereField variable set to salary instead of Name. i.e. count(//tbody/tr/th[./text() = $WhereField]/preceding-sibling::th) + 1
And if you stored the result of query (2) as a variable called $matching_rows and the salary column position as $SalaryPosition, then to return the salary for the row where Name = STU, you could simply finish with: $matching_rows/td[position() = $SalaryPosition]/text(), and you would get the answer 25k.
TL;DR
In summary, as an XPath 1.0 one-liner to get the salary for the row with Name = STU:
//tbody/tr/td[position() = count(//tbody/tr/th[./text() = 'Name']/preceding-sibling::th) + 1][./text() = 'STU']/../td[position() = count(//tbody/tr/th[./text() = 'salary']/preceding-sibling::th) + 1]/text()

Related

How do I find the value of X cells after a matched contains with xpath and lxml

I have a document with multiple rows that has a value in the 4th TD element that I can't figure out how to retrieve. There is nothing unique in the tags so I have to match based on the word TOTAL, and then get the value I need from the 4th TD in the existing row. This is one TR for illustration:
<TR>
<TD ALIGN="right" COLSPAN="30" bgcolor=d8caca><div class=small4>SECTION TOTAL</div></TD>
<TD ALIGN="right" COLSPAN="8" bgcolor=d8caca> </TD>
<TD ALIGN="right" COLSPAN="13" bgcolor=gold><div class=small4> 11.907531</div>
</TD>
<TD ALIGN="right" COLSPAN="13" bgcolor=gold><div class=small4> $773.10</div></TD>
</TR>
I want to match on the word "TOTAL" and then get the value exactly three cells later, or in this case, $773.10.
This successfully gathers each of the "TOTAL" text in an array without issue:
titles = tree.xpath("//tr/td[contains(., 'TOTAL')]//text()")
However, I am unable to get the values in the last element. I've tried numerous variations of the following searching for the TOTAL and then trying to use following or following-sibling to no avail:
totals = tree.xpath("//tr/td[contains(., 'TOTAL')]/../following::td[4]/div/text()")
...but I either get an array of the non-breakable space from the immediate next TD after the TOTAL, no data at all, or "element" references that when expanded to text are null. How do I properly get the value inside td[4] in the existing TR after the contains is matched?
I am trying to get every occurence, not just one, so that the titles and totals arrays are a 1:1 match. If there is a way to do a key=>value pairing that'd be even better.
You can use following-sibling axis to get td located after td that contain text "TOTAL" in the same parent, and then filter the result further to get only the last of such td using predicate [last()], then return the child div/text() :
query = "//tr/td[contains(., 'TOTAL')]/following-sibling::td[last()]/div/text()"
titles = tree.xpath(query)
xpathtester demo: http://www.xpathtester.com/xpath/5cf0aa473d030da66de1bec73bcb8795

How can I support rule definition from a user for my business logic processing?

I have a case where I have an existing method that does a specific kind of processing. I have setup a database table that it checks and if a specific value in a column exists it uses the value in one of the columns.
Example: let's say that I have a method that charges a user. And I have in the table a row that has a column for the country and a column for reduction percentage. So while I am processing the user if the user's country exists in the table I use the value of the column to reduce the price. So far so good.
My question is how could I enhance my design in order to add more general/complex rules?
E.g. I would like to support some kind of interface that the user specifies rules e.g. a user's age or a product weight etc and based on this rules my code processing can figure out how to apply them?
I mean how could I extend my simple table and business logic processing with the country/percentage values to a small rule based setup?
I don't need really complex rules. Just the ability to be let the define a rule if needed
You have to support a certain set of operators, as well as possible fields to be checked against the rule and certain events when the rule is fullfilled.
I would suggest something like this: jsFiddle
<table>
<tr>
<td>Field</td>
<td>
<select><option>Country</option><option>Age</option></select>
</td>
</tr>
<tr>
<td>Operator</td>
<td><select><option>greater than</option><option>smaller than</option><option>not empty</option></select>
</td>
</tr>
<tr>
<td>Value</td>
<td><input id="value" type="text" /></td>
</tr>
<tr>
<td>action</td>
<td><select><option>10% discount</option><option>other stuff</option><option>other stuff 2</option></select></td>
</tr>
</table>
That's just a very quick example of how it could look. You can add any operators and actions you want. You could also include a target field for example. But what's actually in the dropdowns depends on your requirements.

Using XPath to find a dynamic table value

In this table with dynamically changing prices, I wish to always select the link belonging to the first price over $400,00 in XPath 1.0. The correct solution might not always be in the second row, so tr[2]/td[1] will not always be the correct result.
<table>
<tr>
<td>1</td>
<td>-$200,00</td>
</tr>
<tr>
<td>2</td>
<td>$500,00</td>
</tr>
<tr>
<td>3</td>
<td>$100,00</td>
</tr>
</table>
My (non-working) XPath that comes closest so far is:
//tr/td[2][starts-with(.,'$')]/(number(substring-after(.,'$')))>400.00/preceding-sibling::td
It selects the prices by using td[2]
It only selects the prices that have positive values (I don't need the negative values anyway)
It removes the $ signs from the remaining prices
Here is the problem:
I'm trying to use number to convert the strings into numbers so I can compare them to 400 (which is not working)
After that I try to select the corresponding link after the right price has been found.
Any help would be really appreciated (I'm just a simple tester getting dragged into the magical world of test automation) :)
I wish to always select the link belonging to the first price over $400,00 in XPath 1.0.
That would be
//td[number(translate(normalize-space(), ',$', '.')) > 400]/..//a
Note that I translate , to . and $ to nothing**, so if your numbers are formatted any further (digit grouping, for example) this might not be 100% correct yet. Know your data, make the appropriate changes.
For the fun of it (and to demonstrate XPath's flexibility), here's a different path with the same result:
//a[../..//td[number(translate(normalize-space(), ',$', '.')) > 400]]
** translate() replaces one list of characters with another:
translate('abc', 'ac', 'AC') returns 'AbC'
translate('abc', 'ac', 'A') returns 'Ab'.

Parameters and Loops in snippets

I would like to make a snippet that makes an HTML table.
Here are some examples of things to type :
table name address city
- table team wins losses draws
- table views clicks clickthrough
This is what I want it to output : a table with a columns for each of the fields (with 'table' triggering the snippet).
I'd also like to run these field names through a function to transform them (for example to field names - "First Name" -> 'first_name'.
Is this possible? How would I do it?
Not exactly what you want, but I would go with Emmet (here is a handy cheet sheet). There is a Sublime package available, so it's easy to install. It might be a little overwhelming at first, but once you start to use it, you will get the hang of it and it will speed up your html/css production.
Type table>tr*3>th and hit tab at the end. This will produce:
<table>
<tr>
<th></th>
</tr>
<tr>
<th></th>
</tr>
<tr>
<th></th>
</tr>
</table>
Then you can tab to the ths to type in your column headers.

Updating Table dynamically - Ajax HTML

I am trying to update the table as new records come in for table below:
I have got the part where I need to get live information using Ajax. I am using the <tr id = {$university}> as ids to create new rows or update existing. But the updating doesn't seem to work. i.e. If a new student entry is made for University A, than adding a new HTML code. So my existing HTML code looks like
<tr id = "A">
<td>A</td>
<td>Mr. X</td>
<td>a#b.com</td>
</tr>
<tr id = "A">
<td></td>
<td>Mr. Y</td>
<td>e#f.com</td>
</tr>
<tr id = "A">
<td></td>
<td>Mr. S</td>
<td>u#i.com</td>
</tr>
and when I add new data using same <tr id = "A">, it does not append information, but creates a new row:
<tr id = "A">
<td>A</td>
<td>Mr. Z</td>
<td>t#t.com</td>
</tr>
will not append information but create another row in UI. How can I append new information to existing rows?
Added the js code: http://pastebin.com/4tjyUgZa
IDs in HTML are meant to be unique, you shouldn't be duplicating them. Try using a class instead, like <tr class="a">.
I also think you need to revisit your table structure. It looks like what you need are multiple tables, such as table "a" and table "b" that you can then append rows to. The way you are manipulating the table rows just isn't how they're built to work. If you had something like <table id="a"> and <table id="b"> you could then simply target those and add rows easily.
You may also want to make use of a JavaScript framework such as jQuery. It will make manipulating the table much easier and you will be able to write the code much faster.