So I'm trying to generate (dynamic) links through Thymeleaf.
Now the first url I want to link to is /resource/id so I have the following:
<a th:href="|/resource/${resource.id}|" href="#" class="btn btn-default">Edit...</a>
Which works great, and does exactly what you would expect.
So the next url I want to link to is /resource/id/child/id so I try the following:
<a th:href="|/resource/${resource.id}/child/${child.id}|" href="#" class="btn btn-default">Edit...</a>
Which I thought would give me what I wanted. Instead I get:
/resource/3/child%7D?id=4
Which is weird and confusing. I'm not really sure why this happens or how to get what I want which is:
/resource/3/child/4
Any help greatly appreciated. I'm using spring-boot/spring-mvc if it makes any difference.
Update:
Okay, so after re-reading (and comprehending) the documentation, it turns out the the more correct syntax is:
<a th:href="#{/resource/{rid}/child/{cid}(rid=${resource.id} cid=${child.id})}" href="#" class="btn btn-default">Edit...</a>
Now I get the url:
/resource/3/child?id=4
Which while very close is still slightly wrong and confusing.
Does Thymeleaf not support more than one path variable?
I think a comma is missing. Try like this :
th:href="#{/resource/{rid}/child/{cid}(rid=${resource.id},cid=${child.id})}"
Each key/value should be separate with a comma in order to correctly build an URL with multiple path variables.
When working with urls you should better use the url syntax #{...} instead of literal substitution.
For example in your case:
<a th:href="#{/resource/{resource.id}/child/{child.id}}"
href="#" class="btn btn-default">Edit...</a>
(note the absence of the dollar sign in rest resource placeholders)
Have you check the value of child.id? I used it very often like #{|/resource/${resource.id}/child/${child.id}|}.
You can evaluate the syntax wit
<a th:with="child_id='4'" th:href="#{|/resource/${resource.id}/child/${child_id}|}"
and put a <span th:text="${child.id}"></span> to your html to see what value child.id has.
Related
Trying to get the color WHITE out of the line of code.
<a href="javascript:void(0)" class="itemAttr current" title="WHITE" data-
value="WHITE"><img src="https://gloimg.rglcdn.com/rosegal/pdm-product-
pic/Clothing/2019/06/05thumb-img/1559762268621192281.jpg"></a>
I've tried this:
color = driver.find_element_by_xpath("""//p[#id="select-attr-
0"]/a[#href="javascript:void(0)"]#title""").click()
I get this error message:
The string
'//p[#id="select-attr-0"]/a[#href="javascript:void(0)"]#title' is not
a valid XPath expression.
What I want is to get "WHITE".
It looks like you are missing a / before the #title attribute. Try this xpath instead:
//p[#id="select-attr-0"]/a[#href="javascript:void(0)"]/#title
In order to get an attribute value of an element, you need to put '/' before the '#title', so the following should work (provided the parent element p is correctly addressed):
//p[#id="select-attr-0"]/a[#href="javascript:void(0)"]/#title
When working with XPATHs, it is often useful to use one of free online testers to get instant path feedback, e.g. this one
Try using the below xpath snippet.
//p[#id='select-attr- 0']//child::a[#value='WHITE']
I would like to insert the type of my object in my link to. this one is not always the same so I don't want to write it in real letter.
I would like to write something like :
link to "my mission", edit_+ mission.type.downcase + _path(mission)
I don't even know if its possible.
Thanks for your help
You can use instance_eval like:
link_to "my mission", instance_eval("edit_#{mission.type.downcase}_path(mission)")
You might a regular html tag a little easier:
<a href='<%= edit_+ mission.type.downcase + _path(mission)%>'>
mission_path
</a>
I'm trying to crawl some websites, and the data I want can be found either of these places depending on the site:
Page 1:
<div>
<ul>
<li class="asd"> SomeText1 </li>
</ul>
</div>
Page 2:
<div>
<ul>
<li class="dsa"> SomeText2 </li>
</ul>
</div>
I would like an XPath expression which tries to select SomeText1 first, and if it doesn't exist, tries to get SomeText2.
I've tried //li[#class="asd"]/text() or //li[#class="dsa"]/text(), but this doesn't seem to cut it.
Am I using the or operator wrong? If so, how is it supposed to be used?
EDIT
I'm trying to feed a crawler an XPath in order to find information to store in a DB. On a given webpage, can the information I'm trying to get be two different places?
Which means webpage 1 could be:
<AA>
<BB>
<CC> Test </CC>
</BB>
</AA>
and on another there could be
<DD>
<EE>
<FF> Test </FF>
</EE>
</DD>
How can I construct an XPath expression which can say either do
AA/BB/CC or (if it fails/doesn't exist) DD/EE/FF?
You can shorten it to:
//li[#class = 'asd' or #class = 'dsa']/text()
Having said that, "not working" is never an accurate description of what went wrong. A potential source of error is double quotes instead of single quotes. If there are double quotes arround the expression, any quotes inside must be single.
Am I using the or operator wrong ?
No, your usage of the or operator is fine. Something else went wrong. (To really diagnose your problem, we'd need more context).
Try...
//li[#class="asd" or #class="dsa"]/text()
My xpath is :
//*[#id='form_MenuBar:j_id24']/span
and the value # 24 changes.
//*[#id='form_MenuBar:j_id48']/span
I tried but doesn't works.
driver.findElement(By.xpath("//a[contains(#id,'form_MenuBar:j_id$')]/span"));
Source XML:
<li class="ui-menuitem ui-widget ui-corner-all ui-menuitem-active" role="menuitem">
<a id="form_MenuBar:j_id24" class="ui-menuitem-link ui-corner-all ui-state-hover" href="/Demand/j_spring_security_logout">
<span class="ui-menuitem-text">Log off</span>
</a>
</li>
Just try
driver.findElement(By.xpath("//a[contains(#id,'form_MenuBar:j_id')]/span"));
If you are using contains in xpath no need to use '$'.
It appears that you are using java so I'll try to answer it based on that. I'm not a java developer so I apologize if it's not syntactically correct.
If all that is changing is the number within the ID, and you know the ID, you could do:
driver.findElement(By.id(String.format("form_MenuBar:j_id%d", the_id));
Also, I'm not sure about your application that you are testing, but if there are multiple elements that have an id beginning with "form_MenuBar:j_id", then findElement will only find the first one, which might not be the link you are attempting to find.
you could use findElements which will return a list of all elements that match that and then iterate through those until you find the one you really want.
Simplified example
<td>caption</a>
<a id="tt-1">text1</a>
<a id="tt-2">text2</a>
<td>topics</td>
<a id="tt-3">text3</a>
<a id="tt-4">text4</a>
<a id="tt-5">text5</a>
What I need is to match all a elements below <td>topics</td>.
Note that there are plenty of elements between those elements in example. Also <td> may be enclosed into other elements.
My current real-world XPath expression looks like this
//a[contains(#id,'tt-')]
Updated to be closer to real-world
Another update to clarify.
Based on your statement "What I need is to match all a elements below <td>topics</td>"
//td[.='topics']/a
I'm sure that's not the whole story, though.
Based on your updated example:
//a[starts-with(#id, 'tt-') and preceding-sibling::td[1] = 'topics']