Smarty: Restart {cycle} using nested {sections} - smarty

I am trying to generate background colors for multiple tables that are contained withing a {section} ... {/section} block, but if I don't give names to the {cycle} functions, the cycle is continued, not restarted the next time it is encountered. The same problem occurs when I use named cycles and the same named cycle repeats in a section.
Example:
{section name=i loop=$tables}
<table>
{section name=j loop=$tables[i].data}
<tr class="{cycle name=bgcolor values='odd_row,even_row'}">
..
..
..
</tr>
{/section}
</table>
{/section}
How can I get the {cycle} to reset its self on each iteration of {section name=j}? Is it possible to compose names in Smarty? (use something like {cycle name=bgcolor.$i})
Note: I have the same issue on another page which is included multiple times in a single .tpl and every time it shows a table, the background color cycle continues from where it left instead of resetting its self. I understand this is normal behavior (since there is no way for Smarty to know where my cycle begins), but I would like to change it.

Used reset=true like this:
{section name=i loop=$tables}
<table>
{cycle name=bgcolor print=false reset=true values='odd_row,even_row'}
{section name=j loop=$tables[i].data}
<tr class="{cycle name=bgcolor values='odd_row,even_row'}">
..
..
..
</tr>
{/section}
</table>
{/section}

Related

get specifc node position using xpath

I've been strugguling to select a specifc node.
My query consists of two operations. First I need to get the position of a node using this:
count((//th[text()="TEST"])[1]/preceding-sibling::*)+1
and then I do this
(//th[position() = count((//th[text()="TEST"])[1]/preceding-sibling::*)+1])
When I test this query on chrome, it doesn't work. but when I execute them separately it works. Any idea what is wrong ?
Here is the HTML code:
<tbody>
<tr>
<th>TEST</th>
<th>TVA réduite<sup>(2)</sup></th>
<th>Prix TVA 20%</th>
<th>Surface</th>
<th>Etage</th>
<th>Orientation</th>
<th>Cave</th>
</tr>
<tr data-lot-id="0098__981104102">
<td>My Value</td>
<td>462 000€</td>
<td><strong>525 500 €</strong></td>
<td>100.23m²</td>
<td>10</td>
<td>Est</td>
<td>Non</td>
</tr>
</tbody>
I believe you are trying to get the value based on the header.
Scenario 1: Get td value based on th (header)
//td[position()=count(//th[normalize-space(.)='TEST']/preceding-sibling::th)+1]
Screenshot:
Scenario 2: Select the header based on the header text position(you don't need such a complex xpath for this simple though ;-) )
//th[position()=count(//th[normalize-space(.)='TEST']/preceding-sibling::th)+1]
Screenshot:

Xpath to match following sibling in another node

This is my html code:
<tr>
<th class="left_cont"><strong>Hello world</strong></th>
<td class="right_cont padding_left16px"><strong>Hi There</strong></td>
</tr>
Now to select the text Hellow world i used.
//strong[contains(text(),'Hello world')]
Works fine for me.
Now I need to select the text Hi there relatively to the hello world text.
I need to do something like this but I can't figure out.
//strong[contains(text(),'Hello world')]/following-sibling::strong
Doesn't work out for me.
Elements with sibling relations are parent of <strong> instead of <strong> it self, so you can try this way :
//*[strong[contains(.,'Hello world')]]/following-sibling::*[strong]/strong
Or if you are sure parents involved are always <th> and <td> :
//th[strong[contains(.,'Hello world')]]/following-sibling::td[strong]/strong
2nd "strong" element is not actually sibling of the first one. But wrapping "td" elements are siblings. So you could probably use
//strong[contains(text(),'Hello world')]/../following-sibling::td/strong

XPath get only first Parent of nested HTML

I am newbie in XPath. Can someone explain how to resolve this problem:
<table>
<tr>
<td>
<table>
<tr>
<td>
<table>
<tr>
<td>Label</td>
<td>value</td>
</tr>
</table>
</td>
</tr>
</table>
</td>
</tr>
</table>
I try to get <tr> which contains Label value, but it does not work for me,
Here is my code :
//td[contains(.,'Label')]/ancestor::tr[1]
Desired result:
<tr>
<td>Label</td>
<td>value</td>
</tr>
Can someone help me ?
This expression matches the tr that you want:
//tr[contains(td/text(), 'Label')]
Like yours, this starts by scanning all tr elements in the document, but this version uses just a single predicate. The td/text() limits the test to actual text nodes which are grandchildren of the row. If you just used td, then all of the td's descendant text nodes would be collected and concatenated, and the outer tr would match.
UPDATE: Also, for what it's worth, the reason your expression isn't working is that the ancestor axis returns elements in document order, not "outward" from the point of the context node. This is something I've run into myself, as it is somewhat unintuitive. To make your approach work, you would need to say
//td[contains(.,'Label')]/ancestor::tr[last()]
instead of
//td[contains(.,'Label')]/ancestor::tr[1]
I had the same issue, except that the text 'Label' was sometimes in a nested span, or even further nested in the td. For example:
<td><span>Label</span></td>
The previous answer only finds 'Label' if it is in a text element that is a direct child of the td. This issue is a bit harder because we need to search for a td that contains the text 'Label' in any of its children. Since the tds are nested, all tds qualify as having a descendant that contains the text 'Label'. So, the only way I found to overcome this is to add a check that makes sure that the td we select does not contain a td with the search text.
//td[contains(., 'Label') and not(.//td[contains(., 'Label')])]/ancestor::tr[1]
This says give me all of the tds that have a decedent text containing 'Label', but exclude all tds that contain a td that has a decedent text containing 'Label' (nesting ancestors). This returns the child most td that contains the text. Then you can go back to the tr that contains this td using ancestor.
Also, if you just want the lowest table that contains text use this:
//table[contains(., 'Label') and not(.//table[contains(., 'Label')])]
or you can select the tr directly:
//tr[contains(., 'Label') and not(.//tr[contains(., 'Label')])]
This seems like a common problem, but I didn't see a solution anywhere. So, I decided to post to this old unanswered question in hopes that it helps somebody.

Selenium IDE with XPath to identify cell in table based on other column

Please take a look at the snippet of html below:
<tr class="clickable">
<td id="7b8ee8f9-b66f-4fba-83c1-4cf2827130b5" class="clickable">
<a class="editLink" href="#">Single</a>
</td>
<td class="clickable">£14.00</td>
</tr>
I'm trying to assert the value of td[2] when td[1] contains "Single". I've tried assorted variants of:
//td[2][(contains(text(),'£14.00'))]/../td[1][(contains(text(),'Single'))]
I've used similar notation elsewhere successfully - but to no avail here... I think it's down to td[1] having the nested element, but not sure.
Can someone enlighten as to what I'm getting wrong? :)
Cheers!
What about:
//tr[contains(td[1], "Single")]/td[2]
First select the <tr> containing the <td> matching the text, and then select td[2].
Then,
contains(//tr[contains(td[1], "Single")]/td[2], "£14.00")
should return True.
Or, closer to the expression you tried, you could test if this matches:
//tr[contains(td[1], "Single")]/td[2][contains(., "£14.00")]
See #JensErat's answer to find xth td with td contains in same tr xpath python .
Why not make it simple on yourself, do the if statement in your code. Psuedocode:
Select the top level tr.
Find first td within tr, check to see if it contains Single.
If it does, assert that it contains £14.00
Alternatively, you could just get the text of the top level tr and perform the checks on that text.

Finding if a content exists in a given column in a table, with Capybara or Xpath?

Problem:
Given a table, a specific piece of content should appear in the same column as a specific header.
Clarification:
I can not test the column position numerically, or at least I can't hardcode it that way, since the number of columns can change based on various other conditions and I don't want to make my test that fragile.
Example:
Name || Phone Number || Address
==============================================================
... || ... || ...
Joe || 555-787-7878 || 42 Nowhere Lane, Mulberry, California
... || ... ||
With the code looking like so:
<table>
<tr>
<th>Name</th>
<th>Phone Number</th>
<th>Registered</th>
<th>Address</th>
</tr>
<tr>
...
</tr>
<tr>
<td>Joe</td>
<td>555-377-7347</td>
<td>Yes</td>
<td>42 Nowhere Lane1, Mulberry1, California</td>
</tr>
<tr>
<td>Jerry</td>
<td>555-787-7878</td>
<td>Yes</td>
<td>50 Nowhere Lane, Mulberry, California</td>
</tr>
<tr>
<td>Tom</td>
<td>555-678-0987</td>
<td>No</td>
<td>43 Nowhere Lane2, Mulberry2, California</td>
</tr>
<tr>
...
</tr>
</table>
Scenario:
I want to insure the correct address (42 Nowhere...) appears in the column with the header "Address".
How can I do this?
The solution might be as simple as a decent xpath query, to be honest, perhaps I don't even need anything particularly "Capybara" related!
I came across similar one, but here I need to check whether 'Jerry' registered or not. Please help me how can i automate using ruby/capybara
Thanks in Advance
I think #Snekse is very close. Here are some expressions that have been tested. The following returns the table cell corresponding to the th whose value is Address:
/table/tr/td[(count(../../tr/th[.='Address']/preceding-sibling::*)+1)]
This can be used to get the value of the cell:
42 Nowhere Lane, Mulberry, California
...which you could then use to perform the final test:
/table/tr/td[(count(../../tr/th[.='Address']/preceding-sibling::*)+1)]
[.='42 Nowhere Lane, Mulberry, California']
This will return the cell itself, if the addresses match. It will return an empty node-set, which will evaluate to false in a boolean context, if no such node exists.
You probably also need to specify the row you're testing, which can be done with a slight modification to the start of the expression:
/table/tr[$n]/<rest_of_expression>
...where $n is the index of the row to select.
I would think you would first have to get the position of Address, then use that information to get the value from the data table.
So something like:
var x = count(/table/tr/th[.='Address']/preceding-sibling::*)+1.
var address = /table/tr/td[position()=${x}]
Or combine it into something like:
/table/tr/td[position()=(count(/table/tr/th[.='Address']/preceding-sibling::*)+1.)]
NOTE: I didn't run these statements, so I have no idea if they are valid xpath syntax or not, but it should be close enough to get you there.
REFERENCE: Find position of a node using xPath

Resources