I have an .aspx page and I'm trying to locate a textbox via the selenium UI. The id is: p_lt_ctl01_pageplaceholder_p_lt_ctl00_SignUpFree_txtFirstName
I've tried: id=*._txtFirstName
and: id=glob:*_txtFirstName
Is there a better way other than CSS to locate a textbox whose id may change each time it's compiled?
You can't put wildcards in an id "selector". Either you use id=whole_id_here or don't.
Fortunately, for your case, you can use the CSS selector:
[id*=_txtFirstName]
In Selenium IDE, use it like:
css=[id*=_txtFirstName]
Example Selenium IDE source snippet:
<tr>
<td>storeText</td>
<td>css=[id*=_txtFirstName]</td>
<td>x</td>
</tr>
<tr>
<td>echo</td>
<td>${x}</td>
<td></td>
</tr>
Note: If _txtFirstName is always at the end, you can also use the CSS locator with $ instead of * (it is more restrictive, will only match if it is at the end, while * matches if it is anywhere): [id$=_txtFirstName]. (In Selenium IDE, naturally, use it like: css=[id$=_txtFirstName].)
You could try using contains
[contains(#id,'_txtFirstName')]
Related
With Delphi Rio, I am using an HTML/DOM parser. I am traversing the various nodes, and the parser is returning attributes/tags. Normally these are not a problem, but for some attributes/tag, the string returned includes multiple attributes. I need to parse this string into some type of container, such as a stringlist. The attribute string the parser returns already has the '<' and '> removed.
Some examples of attribute strings are:
data-partnumber="BB3312" class=""
class="cb10"
account_number = "11432" model = "pay_plan"
My end result that I want is a StringList, with one or more name=value pairs.
I have not used RegEx to any real degree, but I think that I want to use RegEx. Would this be a valid approach? For a RegEx pattern, I think the pattern I want is
\w\s?=\s?\"[^"]+"
To identify multiple matches within a string, I would use TRegex.Matches. Am I overlooking something here that will cause me issues later on?
*** ADDITIONAL INFO ***
Several people have suggested to use a decent parser. I am currently using the openSource HTML/DOM parser found here: https://github.com/sandbil/HTML-Parser
In light of that, I am posting more info... here is an HTML Snippet I am parsing. Look at the line I have added *** at the end. My parser is returning this as
Node.AttributeText= 'data-partnumber="B92024" data-model="pay_as_you_go" class="" '
Would a different HTML DOM parser return this as 3 different elements/attributes? If so, can someone recommend a parser?
<section class="cc02 cc02v0" data-trackas="cc02" data-ocomid="cc02">
<div class="cc02w1">
<div class="otable otable-scrolling">
<div class="otable-w1">
<table class="otable-w2">
<thead>
<tr>
<th>Product</th>
<th>Unit Price</th>
<th>Metric</th>
</tr>
</thead>
<tbody>
<tr>
<td class="cb152title"><div>MySQL Database for HeatWave-Standard-E3</div></td>
<td><div data-partnumber="B92024" data-model="pay_as_you_go" class="">$0.3536<span></span></div></td> *****
<td><div>Node per hour</div></td>
</tr>
<tr data-partnumber="B92426">
<td class="cb152title">MySQL Database—Storage</td>
<td><span data-model="pay_as_you_go" class="">$0.04<span></span></span></td>
<td>Gigabyte storage capacity per month</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</section>
The documentation for the parser you are using says TDomTreeNode has an AttributesText property that is a "string with all attributes", which you have shown examples of. But it also has an Attributes property that is "parsed attributes" provided as a TDictionary<string, string>. Have you tried looking into the values of that property yet? You should not need to use a RegEx at all, just enumerate the entries of the TDictionary instead, eg:
var
Attr: TPair<string, string>;
for Attr in Node.Attributes do begin
// use Attr.Key and Attr.Value as needed...
end;
(As the OP asked about using a RegEx to parse attribute=value pairs, this answers the question directly, which other users may be looking for in the future.)
RegEx based answer
Using a RegEx is extremely powerful, from the data you have provided you can extract the attribute name and value pairs using:
(\S+)\s*=\s*(\"?)([^"]*)(\2|\s|$)
This uses grouping and can be explained as follows:
The first result group is the attribute name (it matches non-whitespace characters)
The second result group is an enclosing " if present, otherwise an empty string
The third result group is the value of the attribute
As RegExes can be run recursively you can use MatchAgain to see if there's another match and so read all of the attributes recursively.
procedure ParseAttributes(AInput: String; ATarget: TStringList);
var
LMatched: Boolean;
begin
pRegEx:=TPerlRegEx.Create;
try
pRegEx.RegEx:='(\S+)\s*=\s*(\"?)([^"]*)(\2|\s|$)';
pRegEx.Subject:=AInputData;
LMatched:=pRegEx.Match;
while LMatched do
begin
ATarget.Add(pRegEx.Groups[1].'='+'"'+pRegEx.Groups[3]+'"');
LMatched:=pRegEx.MatchAgain;
end;
finally
pRegEx.Free;
end;
end;
Disclaimer: I haven't tried compiling that code, but hopefully it's enough to get you started!
Practical Point: With respect to the actual problem you posed with your DOM parser - this is a task that there are existing solutions for so a practical answer to solving the problem may well be to use a DOM parser that works! If a RegEx is something you need for whatever reason this one should do the job.
I am trying to add .click() to this line of HTML using Selenium webdriver (PhantomJS).
I am new to Selenium and can't find a way to distinctly click on search within attribute such as below (see HTML).
Using the following find_element_by.. is not specific enough. The only unique part is the attribute value.
find_element_by_id
find_element_by_name
find_element_by_xpath
find_element_by_link_text
find_element_by_partial_link_text
find_element_by_tag_name
find_element_by_class_name
find_element_by_css_selector
<td onclick="show_ad('2','1','/Nadlan/salesDetails.php','ElemID','339efe7a8643d231c48098cc593e3705f13','644');" >Elems</td>
In my index.gsp for one of the column values for a table I provide the following:
<td><g:link action = "redirect(url: 'http://www.google.com')">www.google.com</g:link></td>
However, the link that shows on the page is ->
http://localhost:8080/APP_NAME/VIEW_NAME/redirect(url: 'http://www.google.com')
What's the workaround to avoid the inclusion of the base url in the beginning. I want the link to be the absolute URL ->
http://www.google.com
Based on some of the comments below, the following works ->
<td><a href='http://www.google.com'>www.google.com</a></td>
However, when I reference the field of a bean that I wish to display like this ->
<td><a href=${fieldValue(bean: testRunInstance, field: "artifactLink")}>${fieldValue(bean: testRunInstance, field: "artifactLink")}</a></td>
the link displays correct (www.google.com), while the actual link resolves to ->
http://localhost:8080/APP_NAME/www.google.com
How do I eliminate the reference to the below Base URL?
http://localhost:8080/APP_NAME/
or this, if you want <g:link>
<g:link url="http://www.google.com">www.google.com</g:link>
Use the tag anchor of the standard HTML
<a href='http://www.google.com'>www.google.com</a>
EDIT
You can change:
<td><a href=${fieldValue(bean: testRunInstance, field: "artifactLink")}>${fieldValue(bean: testRunInstance, field: "artifactLink")}</a></td>
By:
<td>
<a href="http://${testRunInstance.artifactLink}">
${fieldValue(bean: testRunInstance, field: "artifactLink")}
</a>
</td>
i think you can use
<g:link url="http://www.google.com">www.google.com</g:link>
// Example, where artifactLink has a value, ddg.gg
<g:link base="http://" uri="${bean.artifactLink}">${bean.artifactLink}</g:link>
// Generates
ddg.gg
// Example, where artifactLink has a value, http://ddg.gg
<g:link base="http://" uri="${bean.artifactLink}">${bean.artifactLink}</g:link>
// Generates
http://ddg.gg
// Example, where artifactLink has a value, https://ddg.gg
<g:link base="http://" uri="${bean.artifactLink}">${bean.artifactLink}</g:link>
// Generates
https://ddg.gg
It ignores the base attribute altogether, when encounter a protocol in front of the uri value. Notice, it doesn't repeat http:// in the 2nd example, and used https:// instead, in the last one.
Moreover, you can specify target="_blank", so page loads in a new tab or window.
NB: Should work for Grails 3.2 or >.
The HTML is as follows:
<div class="item link-color-1
automated link-track logout-link"
data-track-category="Logout"
data-track-action="Logout from /myaccount/mymoney/cashier"
data-data-automated-function="clickTracker"> logout </div>
To find the x path of a link, tried something like: //*[contains(#data-track-category='Logout']. But its not working. Please help.
If you are just trying to find the element itself (and not the value of the attribute as your question title implies), you could always use CSS (its my selector of choice over XPath).
You have not indicated which language bindings you use, so this is how I would find it in Ruby by using only the data-track-category attribute to select the element:
#driver.find_element(:css => "[data-track-category='Logout']")
Of course, the same applies across all the bindings. Just use the value "[data-track-category='Logout']" for your CSS method.
You can always store the given element in a WebElement and then using the getAttribute() method. You can find the documentation here
WebElement myDiv = driver.findElement(By.className("logout-link"));
String attributeValue = myDiv.getAttribute("data-track-category");
This should work on Java. Not sure that's the language you are looking for or if you must use regex for it.
I'm exploring Django and got this particular problem.
How do I prepend <span class="label">Note:</span> inside {{article.content_html|safe}}?
The content of {{article.content_html|safe}} are paragraph blocks, and I just wanna add <span class="label">Note:</span> in the very first paragraph.
Thanks!
Sounds like you want to write a custom tag that uses BeautifulSoup to parse the HTML and inject the fragment.
There's no easy way. You can easily prepend to all articles.
<span class="label">Note:</span>
{{article.content_html|safe}}
If that doesn't help you consider changing the structure of article.content_html so you can manipulate with blocks from django templates, so it should look something like this
{{article.content_header}}
<span class="label">Note:</span>
{{article.content_html}}
If that solution is not feasible to you and you absolutely need to parse and modify the content of article.content_html, write your own custom filter that does that. You can find documentation about writing custom filters here http://docs.djangoproject.com/en/dev/howto/custom-template-tags/#writing-custom-template-filters.
An alternate approach could be to do this with javascript. In jQuery, it would look something like:
var first_p_text = $("p:first").text()
$("p:first").html("<span class="label">Note:</span>" + first_p_text)
Note though that if there are other elements inside your first p, $("p:first").text() will grab the text from those as well - see http://api.jquery.com/text/
Of course, this relies on decent javascript support in the client.
jQuery is the simplest and easiest to implement. You only need one line with the prepend call (documentation):
$('p:first').prepend('<span class="label">Note:</span>');
Explanation: 'p:first' is a jQuery selector similar to the ':first-child' CSS selector. It will select the first paragraph and the prepend call will then insert the span into that selected paragraph.
Note: If there is a paragraph on the page before your content, you may have to surround it with a div:
<div id='ilovesmybbq'>{{article.content_html|safe}}</div>
Then the jQuery call would be:
$('#ilovesmybbq p:first').prepend('<span class="label">Note:</span>');