[WEB] Click on Link Using XPath [Example]

In that case you need to find an XPath that does "id", or use an XPath that references only the part of the "id" that is constant.

1 Like

//*[@id=":4i"]/div/div[2]/span/a

Could you help, which part is constant here?

Or you gotta check entire page code?

The part of the "id" that does NOT change with each browser.

To be more helpful, I will need the URL, or at least the HTML code for the major section of the page you are trying to use. If you post the HTML, please do so in Code Block.

Facebook Ads page, part where you launch campaigns n settings.

I want to share, but it contains private info.

But yah, notice FB always changes its Xpath 'id' for certain elements.

You could copy the HTML, and change any private info to something made up, but of the same form.
I can't really help without seeing the HTML.

Gmail also guilty of dynamic Xpath IDs.

image

Trash button for example

On my side, its Xpath is showing this:

//*[@id=":jl"]/div/div[2]

I'm sure it's different for everyone else.

Ok, here's an example of the element in Facebook thingy.

<input class="_4b7k _4b7k_big _53rs" data-testid="custom-audience-name-input" placeholder="Name your audience" maxlength="50" value="" style="letter-spacing: normal; color: rgb(28, 30, 33); font-size: 12px; font-family: -apple-system, BlinkMacSystemFont, Arial, sans-serif; line-height: 16px; background: rgb(255, 255, 255); height: 26px; padding-bottom: 6px; padding-top: 6px; text-align: left;">

below is the Xpath-Absolute for it (right click Inspect > Copy Xpath)
//*[@id="facebook"]/body/div[4]/div[2]/div/div/div/div/div/div/div[2]/div/div/div[1]/div[2]/div/div/div/div[1]/div/label/input

so I gotta somehow study up XML n Xpath basics
so could write custom code
to select by either these 2 by Xpath-Attribute
(cause they're constant n don't change dynamically each time whatever)

  • data-testid="custom-audience-name-input"
  • placeholder="Name your audience"

cause from what I understand, the above Xpath is based on Xpath-Absolute/Position. Basically NOT a good way to define Xpath to use in KM, cause it can be dynamic n break

**UPDATE
oh hey, figured it out, Xpath-Attribute

//input[@data-testid='custom-audience-name-input' and @placeholder='Name your audience']

Works, awesome. Now gotta pray these 2 constants won't change in future.

Much thanks.

This helped explained

But wouldn't have been possible without your Xpath macro @JMichaelTX

But stuck at this one

<input class="_4b7k _4b7k_big _53rs" data-testid="edit-name-field" placeholder="Enter your ad set name here..." value="TH - 18+" style="letter-spacing: normal; color: rgb(28, 30, 33); font-size: 12px; font-family: -apple-system, BlinkMacSystemFont, Arial, sans-serif; line-height: 16px; background: rgb(255, 255, 255); height: 26px; padding-bottom: 6px; padding-top: 6px; text-align: left;">

Xpath-Absolute
//*[@id="aymt-parent-switch-to-quick-creation-SCROLLING"]/div[2]/div[1]/div/div[2]/label/input

Xpath-Attribute? (not working)
//input[@data-testid='edit-name-field' and @placeholder='Enter your ad set name here...']

Xpath-Attribute? (not working)
//input[@class='_4b7k _4b7k_big _53rs' and @data-testid='edit-name-field' and @placeholder='Enter your ad set name here...']

Hey @JMichaelTX

Could you please advise on how to modify the JavaScript to execute it in AppleScript.

I would like to set an XPath in JS instead of using KM action but not sure how exactly to make it work.

set java to "(function run (pXPathStr) {
  'use strict';

var xPathStr = document.kmvar.xPath;
  
var elemFound =  document.evaluate(
      xPathStr, document, null, 0, null
    ).iterateNext();
    
  if (elemFound) {
    elemFound.click();
  }
  else {
  }
  
  return returnResults;

})();

/* 
*/"

tell application "Safari" to tell the front document to set theText to do JavaScript java

UPDATE:
After spending hours i finally found a way to do it:

tell application "Safari"
	do JavaScript "path = '//*[@id=\"yw5\"]/li[7]/a'; 
theNode = document.evaluate(path, document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue;
theNode.click();" in front document
end tell

@JMichaelTX I have just discovered this script and it looks very powerful!

I'm trying it out on my banking site without much luck though. The HTML for an OFX export button is
<input value="Export" readonly="" id="export" style="margin-left: 25%;" class="formButton">
and both Safari and Chrome report the xPath to be
//*[@id="export"]
When I run the macro in either Safari or Chrome, I get the error
[ERROR] Element NOT FOUND for XPath: //*[@id="export"]
Do you have any suggestions for debugging?

That should work, unless the HTML code is inside of a frame. if you will post a much wide block of HTML code around the <input...> element I'll take a look at it. Start with the HTML many lines above the <input>.

@JMichaelTX thank you for your help. Here is the entire panel. The input is right after <div class="footer">. Please let me know if I can provide anything else.

<div class="panelNavigation">
			<ul class="listBy tabSet">
				<li class="left navItem sel" ref="PostedTransactions"><a>List by Date</a></li>
				<li class="mid navItem" ref="ListByType"><a>List by Type</a></li>
				<li class="right navItem" ref="Search"><a>Search</a></li>
			</ul>

			<ul class="filters">
				<!-- <li class="filter" id="Filter-Trans"><a return false;" class="currentState">Filter: All</a></li> -->
				<li class="filter" id="Filter-Export"><a>Export</a></li>
			</ul>

			<div id="exportTransactions" class="panelDropDown2" style="display: block; visibility: visible;">
				<div class="ddHead2">
					<div class="ddFilterTab3">
						<a>Export</a>
					</div>  
				</div>
				
				<div class="bd">
                    <div class="noError">
                    You may export your last 90 days of transaction history.
					To access up to 7 years of transaction history,
					please visit Online Statements.
                    </div>
                    <div class="header">
                        <p style="font-size: 1.1em;font-weight: bold;color: black;margin-left: 20%;padding-left: 6px;">Select a file format:</p>
                    </div>
                    <div class="body">
                        <div>

	                        <ul style="margin-left: 20%;">
	                            <li><input type="radio" name="fileType"><a data-extn="qfx">Quicken (.QFX)</a></li>
	                            <li><input type="radio" name="fileType"><a data-extn="qbo">Quickbooks (.QBO)</a></li>
	                            <li><input type="radio" name="fileType"><a data-extn="ofx">Microsoft Money (.OFX)</a></li>
	                            <li><input type="radio" name="fileType"><a data-extn="csv">Microsoft Excel (.CSV)</a></li>
	                        </ul>
                        </div>
                    </div>
                    <div class="footer">
                        <input value="Export" readonly="" id="export" style="margin-left: 25%;" class="formButton">
                        <p style="display:block; font-style: italic; font-size: 1em; padding: 0px 10px 10px 10px;">
                        	Sort and search results will not be included in the export.
                        </p>
                    </div>
                   
				</div>
				<div class="Outsidefooter">
                </div>
                
			</div>
		</div>

The XPath should still work. Did you check to see if all of this is within a FRAME?

Instead of using this macro, you can use a Execute a JavaScript in Front Browser action

document.querySelector('#export').click();

If that also does NOT click on the "Export" button, that it is highly likely the whole panel is in a FRAME.

Thanks for the suggestion @JMichaelTX. I turns out that it is within a frame:

<frameset rows="*,1" frameborder="no" framespacing="0" border="0" onunload="forceLogoff()">
	<frame src="/alservlet/SignonInitServlet?HttpLevel=128" name="center" marginheight="0" marginwidth="0" noresize="">
	<frame src="/Marketing/spotlight.html" name="filler" marginheight="0" marginwidth="0" noresize="">
	<frame src="/blank.html" name="vwCimModal" marginheight="0" marginwidth="0" noresize="">
	<frame src="/blank.html" name="vwCim" marginheight="0" marginwidth="0" noresize="">
</frameset>

I tried your JavaScript macro and Safari reported the error
TypeError: null is not an object (evaluating 'document.querySelector('#export').click'). Just for fun, I pasted the same text into the Safari JavaScript console and the Export File did indeed download. That is perplexing...

FYI, I was able to get the job accomplished by searching for the button image and clicking it. That worked great on my 5K iMac, but failed on my laptop, due to the button being below the fold in the browser :frowning:

1 Like

Thanks for the confirmation of what I suspected.

Hello, I've tried to se up the macro that gives me a response on the web page but nothing is clicked so it's not working.
I think the problem rely on XPATH. I've copied form both safari and chrome the XPATH of the link I wont to clic but it doesn't look like a real XPATH with @id= format.,
Here's the XPATH I am getting: /html/body/div[2]/root/div/div[1]/div/div/div[3]/awsm-skinny-nav/div/div/div[2]/awsm-skinny-nav-item[1]/a

Can you please help me?
Thanks

I don't like XPath. I find it hard to learn, understand, and use.
I much prefer querySelector.

Take a look at this post and related posts and see if you can figure it out.

If you still need help, please post a new topic with:

  • URL of page that has the link you want to click
    OR
  • HTML Code around the link, using Code Block.
  • Screenshot identifying the link to click

How do I make it so that it doesn't give me a popup window saying "ok" everytime I use this script

Would a 'Type a Keystroke' action with a return in it do the job?

Look through the macro to find out where it produces the OK dialog, and turn it off.

¬

1 Like