{"id":157,"date":"2024-09-16T21:52:09","date_gmt":"2024-09-16T21:52:09","guid":{"rendered":"https:\/\/nestedflowautomation.com\/?p=157"},"modified":"2024-09-16T21:55:31","modified_gmt":"2024-09-16T21:55:31","slug":"ai-topic-1-distance-algorithms-to-locate-items","status":"publish","type":"post","link":"https:\/\/nestedflowautomation.com\/index.php\/2024\/09\/16\/ai-topic-1-distance-algorithms-to-locate-items\/","title":{"rendered":"AI -Topic 1 &#8211; Distance Algorithms to Locate Items"},"content":{"rendered":"\n<h2 class=\"wp-block-heading\">Objective<\/h2>\n\n\n\n<p>In this post we will try to look into the usage of text similarity algorithms like Levenshtein distance to accurately locate the items in case of dynamically altering pages where the object properties like id, name keep on changing (e.g.: Salesforce Lightening)<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Groundwork<\/h2>\n\n\n\n<p>A typical web page is always having group of web objects structured to complement each other. for example:<\/p>\n\n\n\n<figure class=\"wp-block-image size-full is-style-rounded is-style-rounded--b3f14267c6f190ad9c4f6201c8de6390\"><img loading=\"lazy\" decoding=\"async\" width=\"439\" height=\"168\" src=\"https:\/\/nestedflowautomation.com\/wp-content\/uploads\/2024\/09\/image.png\" alt=\"\" class=\"wp-image-158\" srcset=\"https:\/\/nestedflowautomation.com\/wp-content\/uploads\/2024\/09\/image.png 439w, https:\/\/nestedflowautomation.com\/wp-content\/uploads\/2024\/09\/image-300x115.png 300w\" sizes=\"(max-width: 439px) 100vw, 439px\" \/><\/figure>\n\n\n\n<p>Here, Username label and the input box are structured together.<\/p>\n\n\n\n<p>Full XPath of label: <strong>\/html[1]\/body[1]\/section[1]\/div[2]\/div[2]\/div[1]\/form[1]\/div[1]\/label[1]<\/strong><\/p>\n\n\n\n<p>Full XPath of Input: <strong>\/html[1]\/body[1]\/section[1]\/div[2]\/div[2]\/div[1]\/form[1]\/div[1]\/label[1]<\/strong>\/input[1]<\/p>\n\n\n\n<p>The part of XPaths marked as bold are simililarity between two XPaths.<\/p>\n\n\n\n<p><\/p>\n\n\n\n<p>Similarly, Password: label and corresponding password box are structured together.<\/p>\n\n\n\n<p>Full XPath of label: <strong>\/html[1]\/body[1]\/section[1]\/div[2]\/div[2]\/div[1]\/form[1]\/div[1]\/label[2]<\/strong><\/p>\n\n\n\n<p>Full XPath of Password: <strong>\/html[1]\/body[1]\/section[1]\/div[2]\/div[2]\/div[1]\/form[1]\/div[1]\/label[2]<\/strong>\/input[1]<\/p>\n\n\n\n<p>As you can see above, structured objects are always close to each other in terms of Xpath<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Logic<\/h2>\n\n\n\n<p>Due to the ever-changing development happening in the production pages, Full XPath is not an ideal option for locating web objects. But the labels and associated inputs are always associated with each other in terms of visual and XPath terms as explained above.<\/p>\n\n\n\n<p>Let us try to locate the user name input.<\/p>\n\n\n\n<p><strong><span style=\"text-decoration: underline;\">Step 1<\/span><\/strong>: Locate the label with referential XPath: <strong>\/\/label[contains(.,&#8221;Username:&#8221;)]<\/strong><\/p>\n\n\n\n<p><strong><span style=\"text-decoration: underline;\">Step 2<\/span><\/strong>: Find the Full XPath: <strong>\/html[1]\/body[1]\/section[1]\/div[2]\/div[2]\/div[1]\/form[1]\/div[1]\/label[1]<\/strong><\/p>\n\n\n\n<p><strong><span style=\"text-decoration: underline;\">Step 3<\/span><\/strong>: Find all inputs on the screen and corresponding Full XPaths<\/p>\n\n\n\n<p>var inputList = IWeb.FindElements(By.XPath(&#8220;\/\/input&#8221;));<\/p>\n\n\n\n<p>and find full XPaths for all of the elements.<\/p>\n\n\n\n<p><strong>XPath<\/strong>: \/html[1]\/body[1]\/nav[1]\/div[2]\/div[1]\/div[3]\/div[1]\/form[1]\/div[1]\/input[1]<br><strong>XPath<\/strong>: \/html[1]\/body[1]\/section[1]\/div[2]\/div[1]\/div[3]\/div[1]\/form[1]\/div[1]\/input[1]<br><strong>XPath<\/strong>:<strong> <\/strong><\/p>\n\n\n\n<p>\/html[1]\/body[1]\/section[1]\/div[2]\/div[2]\/div[1]\/form[1]\/input[1]                                  <br><strong>XPath: <\/strong>\/html[1]\/body[1]\/section[1]\/div[2]\/div[2]\/div[1]\/form[1]\/div[1]\/label[1]\/input[1]<br><strong>XPath: <\/strong>\/html[1]\/body[1]\/section[1]\/div[2]\/div[2]\/div[1]\/form[1]\/div[1]\/label[2]\/input[1]<\/p>\n\n\n\n<p>If we apply the string similarity algorithm (create string array by splitting the string with \/ and then comparing how many components of XPaths do match) and compare label full XPath with the full XPath of each input<\/p>\n\n\n\n<p><strong>Label XPath:  <\/strong>\/html[1]\/body[1]\/section[1]\/div[2]\/div[2]\/div[1]\/form[1]\/div[1]\/label[1]<br><strong>XPath<\/strong>: \/html[1]\/body[1]\/nav[1]\/div[2]\/div[1]\/div[3]\/div[1]\/form[1]\/div[1]\/input[1] . Match: 3<br><strong>XPath<\/strong>: \/html[1]\/body[1]\/section[1]\/div[2]\/div[1]\/div[3]\/div[1]\/form[1]\/div[1]\/input[1] . Match: 5<br><strong>XPath<\/strong>: \/html[1]\/body[1]\/section[1]\/div[2]\/div[2]\/div[1]\/form[1]\/input[1] .   Match: 8<br><strong>XPath<\/strong>: <em>\/html[1]\/body[1]\/section[1]\/div[2]\/div[2]\/div[1]\/form[1]\/div[1]\/label[1]\/input[1] . Match: 10<\/em><br><strong>XPath<\/strong>: \/html[1]\/body[1]\/section[1]\/div[2]\/div[2]\/div[1]\/form[1]\/div[1]\/label[2]\/input[1] . Match: 9<\/p>\n\n\n\n<p>The most match found in XPath: <em>html[1]\/body[1]\/section[1]\/div[2]\/div[2]\/div[1]\/form[1]\/div[1]\/label[1]\/input[1] <\/em> which exactly matches the user name input<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Comparison Code<\/h2>\n\n\n\n<p><\/p>\n\n\n\n<p><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code><strong>public <\/strong>static int CalculateSimilarity(string source1, string source2)\n{        \n\/\/return matrix&#91;source1Length, source2Length];\n        string&#91;] Source1Array= source1.Split('\/');\n        string&#91;] Source2Array = source2.Split('\/');\n        int x = 0;\n\n        int source1Length = Source1Array.Length, source2Length = Source2Array.Length;\n        int minLen = Math.Min(source1Length, source2Length);\n        for (i=0;i&lt; minLen; i++)\n        {\n            if (Source1Array&#91;i] == Source2Array&#91;i])\n            {\n                x++;\n            }\n            else\n            {\n                break;\n            }\n        }\n        return x;\n    }<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Code to find Full XPath of any web Object<\/h2>\n\n\n\n<pre class=\"wp-block-code\"><code><strong>public <\/strong>string GetItemFullXpath(IWebElement iret)\n        {\n            string Xpathtrail = \"\";\n            try\n            {\n\n                    string RefTag = iret.TagName;\n                    IWebElement prnt;\n                    IWebElement curr = iret;\n                    int icnt;\n                    int i;\n\n                    while (RefTag!= \"html\")\n                    {\n                        prnt = GetParent(curr);\n                        var children = prnt.FindElements(By.XPath(\"*\"));\n                        icnt = children.Count;\n                        int Tagcnt = 1;\n                        for (i = 0; i &lt; icnt; i++)\n                        {\n                            IWebElement pi = children&#91;i];\n                            if (pi.TagName == RefTag)\n                            {\n                                if (pi.Equals(curr))\n                                {\n                                    Xpathtrail = \"\/\" + RefTag + \"&#91;\" + Tagcnt.ToString() + \"]\" + Xpathtrail;                                    \n                                    break;\n                                }\n                                Tagcnt++;                                \n                            }\n                        }\n                        curr = prnt;\n                        RefTag = curr.TagName;\n                    }\n                    Xpathtrail = \"\/html&#91;1]\" + Xpathtrail;                   \n                }\n                return Xpathtrail;\n            }\n            catch (Exception )\n            {\n\n            }\n        }\n-------------------------------------------------------\n<strong>public  <\/strong>IWebElement GetParent(IWebElement IWebe)\n        {\n            try\n            {\n                return IWebe.FindElement(By.XPath(\"parent::*\"));\n            }\n            catch\n            {\n                return null;\n            }\n        }<\/code><\/pre>\n\n\n\n<p><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Objective In this post we will try to look into the usage of text similarity algorithms like Levenshtein distance to accurately locate the items in case of dynamically altering pages where the object properties like id, name keep on changing (e.g.: Salesforce Lightening) Groundwork A typical web page is always having group of web objects [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[],"class_list":["post-157","post","type-post","status-publish","format-standard","hentry","category-blog"],"_links":{"self":[{"href":"https:\/\/nestedflowautomation.com\/index.php\/wp-json\/wp\/v2\/posts\/157"}],"collection":[{"href":"https:\/\/nestedflowautomation.com\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/nestedflowautomation.com\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/nestedflowautomation.com\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/nestedflowautomation.com\/index.php\/wp-json\/wp\/v2\/comments?post=157"}],"version-history":[{"count":3,"href":"https:\/\/nestedflowautomation.com\/index.php\/wp-json\/wp\/v2\/posts\/157\/revisions"}],"predecessor-version":[{"id":161,"href":"https:\/\/nestedflowautomation.com\/index.php\/wp-json\/wp\/v2\/posts\/157\/revisions\/161"}],"wp:attachment":[{"href":"https:\/\/nestedflowautomation.com\/index.php\/wp-json\/wp\/v2\/media?parent=157"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/nestedflowautomation.com\/index.php\/wp-json\/wp\/v2\/categories?post=157"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/nestedflowautomation.com\/index.php\/wp-json\/wp\/v2\/tags?post=157"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}