需要在 运行 时间从 WebElement 对象检索 xpath 或 css
Need to retrieve xpath or css from WebElement Object at run time
从 WebElement 对象检索 xpath 或 css(任何逻辑)的可能方法有哪些?例如,我通过以下方式创建了 WebElement:
WebElement obj=driver.findElement(By.cssSelector(".hello"));
现在我想从此 WebElement 对象取回一个 By 对象,或者如果我能够检索 xpath 或 css 那么我就能够创建它的 By 对象。给我任何想法。
您应该了解,对于任何给定元素,有许多可能的 XPath 将到达该元素。
我们的软件在记录浏览器会话时自动生成 XPath,并且它使用至少 5 种不同的策略来实现。但是每个生成器都基于相同的基本概念:从目标元素向上迭代树,直到我们找到可以从中构建相对路径的其他可识别元素(例如根或具有 id 的元素)。然后根据可识别的元素和目标元素的路径构建一个 XPath。
尝试实现以下 JavaScript 功能。
// ************************************************************************************************
// XPath
/**
* Gets an XPath for an element which describes its hierarchical location.
*/
this.getElementXPath = function(element)
{
if (element && element.id)
return '//*[@id="' + element.id + '"]';
else
return this.getElementTreeXPath(element);
};
this.getElementTreeXPath = function(element)
{
var paths = [];
// Use nodeName (instead of localName) so namespace prefix is included (if any).
for (; element && element.nodeType == 1; element = element.parentNode)
{
var index = 0;
for (var sibling = element.previousSibling; sibling; sibling = sibling.previousSibling)
{
// Ignore document type declaration.
if (sibling.nodeType == Node.DOCUMENT_TYPE_NODE)
continue;
if (sibling.nodeName == element.nodeName)
++index;
}
var tagName = element.nodeName.toLowerCase();
var pathIndex = (index ? "[" + (index+1) + "]" : "");
paths.splice(0, 0, tagName + pathIndex);
}
return paths.length ? "/" + paths.join("/") : null;
};
this.getElementCSSPath = function(element)
{
var paths = [];
for (; element && element.nodeType == 1; element = element.parentNode)
{
var selector = this.getElementCSSSelector(element);
paths.splice(0, 0, selector);
}
return paths.length ? paths.join(" ") : null;
};
this.cssToXPath = function(rule)
{
var regElement = /^([#.]?)([a-z0-9\*_-]*)((\|)([a-z0-9\*_-]*))?/i;
var regAttr1 = /^\[([^\]]*)\]/i;
var regAttr2 = /^\[\s*([^~=\s]+)\s*(~?=)\s*"([^"]+)"\s*\]/i;
var regPseudo = /^:([a-z_-])+/i;
var regCombinator = /^(\s*[>+\s])?/i;
var regComma = /^\s*,/i;
var index = 1;
var parts = ["//", "*"];
var lastRule = null;
while (rule.length && rule != lastRule)
{
lastRule = rule;
// Trim leading whitespace
rule = this.trim(rule);
if (!rule.length)
break;
// Match the element identifier
var m = regElement.exec(rule);
if (m)
{
if (!m[1])
{
// XXXjoe Namespace ignored for now
if (m[5])
parts[index] = m[5];
else
parts[index] = m[2];
}
else if (m[1] == '#')
parts.push("[@id='" + m[2] + "']");
else if (m[1] == '.')
parts.push("[contains(concat(' ',normalize-space(@class),' '), ' " + m[2] + " ')]");
rule = rule.substr(m[0].length);
}
// Match attribute selectors
m = regAttr2.exec(rule);
if (m)
{
if (m[2] == "~=")
parts.push("[contains(@" + m[1] + ", '" + m[3] + "')]");
else
parts.push("[@" + m[1] + "='" + m[3] + "']");
rule = rule.substr(m[0].length);
}
else
{
m = regAttr1.exec(rule);
if (m)
{
parts.push("[@" + m[1] + "]");
rule = rule.substr(m[0].length);
}
}
// Skip over pseudo-classes and pseudo-elements, which are of no use to us
m = regPseudo.exec(rule);
while (m)
{
rule = rule.substr(m[0].length);
m = regPseudo.exec(rule);
}
// Match combinators
m = regCombinator.exec(rule);
if (m && m[0].length)
{
if (m[0].indexOf(">") != -1)
parts.push("/");
else if (m[0].indexOf("+") != -1)
parts.push("/following-sibling::");
else
parts.push("//");
index = parts.length;
parts.push("*");
rule = rule.substr(m[0].length);
}
m = regComma.exec(rule);
if (m)
{
parts.push(" | ", "//", "*");
index = parts.length-1;
rule = rule.substr(m[0].length);
}
}
var xpath = parts.join("");
return xpath;
};
从 WebElement 对象检索 xpath 或 css(任何逻辑)的可能方法有哪些?例如,我通过以下方式创建了 WebElement:
WebElement obj=driver.findElement(By.cssSelector(".hello"));
现在我想从此 WebElement 对象取回一个 By 对象,或者如果我能够检索 xpath 或 css 那么我就能够创建它的 By 对象。给我任何想法。
您应该了解,对于任何给定元素,有许多可能的 XPath 将到达该元素。
我们的软件在记录浏览器会话时自动生成 XPath,并且它使用至少 5 种不同的策略来实现。但是每个生成器都基于相同的基本概念:从目标元素向上迭代树,直到我们找到可以从中构建相对路径的其他可识别元素(例如根或具有 id 的元素)。然后根据可识别的元素和目标元素的路径构建一个 XPath。
尝试实现以下 JavaScript 功能。
// ************************************************************************************************
// XPath
/**
* Gets an XPath for an element which describes its hierarchical location.
*/
this.getElementXPath = function(element)
{
if (element && element.id)
return '//*[@id="' + element.id + '"]';
else
return this.getElementTreeXPath(element);
};
this.getElementTreeXPath = function(element)
{
var paths = [];
// Use nodeName (instead of localName) so namespace prefix is included (if any).
for (; element && element.nodeType == 1; element = element.parentNode)
{
var index = 0;
for (var sibling = element.previousSibling; sibling; sibling = sibling.previousSibling)
{
// Ignore document type declaration.
if (sibling.nodeType == Node.DOCUMENT_TYPE_NODE)
continue;
if (sibling.nodeName == element.nodeName)
++index;
}
var tagName = element.nodeName.toLowerCase();
var pathIndex = (index ? "[" + (index+1) + "]" : "");
paths.splice(0, 0, tagName + pathIndex);
}
return paths.length ? "/" + paths.join("/") : null;
};
this.getElementCSSPath = function(element)
{
var paths = [];
for (; element && element.nodeType == 1; element = element.parentNode)
{
var selector = this.getElementCSSSelector(element);
paths.splice(0, 0, selector);
}
return paths.length ? paths.join(" ") : null;
};
this.cssToXPath = function(rule)
{
var regElement = /^([#.]?)([a-z0-9\*_-]*)((\|)([a-z0-9\*_-]*))?/i;
var regAttr1 = /^\[([^\]]*)\]/i;
var regAttr2 = /^\[\s*([^~=\s]+)\s*(~?=)\s*"([^"]+)"\s*\]/i;
var regPseudo = /^:([a-z_-])+/i;
var regCombinator = /^(\s*[>+\s])?/i;
var regComma = /^\s*,/i;
var index = 1;
var parts = ["//", "*"];
var lastRule = null;
while (rule.length && rule != lastRule)
{
lastRule = rule;
// Trim leading whitespace
rule = this.trim(rule);
if (!rule.length)
break;
// Match the element identifier
var m = regElement.exec(rule);
if (m)
{
if (!m[1])
{
// XXXjoe Namespace ignored for now
if (m[5])
parts[index] = m[5];
else
parts[index] = m[2];
}
else if (m[1] == '#')
parts.push("[@id='" + m[2] + "']");
else if (m[1] == '.')
parts.push("[contains(concat(' ',normalize-space(@class),' '), ' " + m[2] + " ')]");
rule = rule.substr(m[0].length);
}
// Match attribute selectors
m = regAttr2.exec(rule);
if (m)
{
if (m[2] == "~=")
parts.push("[contains(@" + m[1] + ", '" + m[3] + "')]");
else
parts.push("[@" + m[1] + "='" + m[3] + "']");
rule = rule.substr(m[0].length);
}
else
{
m = regAttr1.exec(rule);
if (m)
{
parts.push("[@" + m[1] + "]");
rule = rule.substr(m[0].length);
}
}
// Skip over pseudo-classes and pseudo-elements, which are of no use to us
m = regPseudo.exec(rule);
while (m)
{
rule = rule.substr(m[0].length);
m = regPseudo.exec(rule);
}
// Match combinators
m = regCombinator.exec(rule);
if (m && m[0].length)
{
if (m[0].indexOf(">") != -1)
parts.push("/");
else if (m[0].indexOf("+") != -1)
parts.push("/following-sibling::");
else
parts.push("//");
index = parts.length;
parts.push("*");
rule = rule.substr(m[0].length);
}
m = regComma.exec(rule);
if (m)
{
parts.push(" | ", "//", "*");
index = parts.length-1;
rule = rule.substr(m[0].length);
}
}
var xpath = parts.join("");
return xpath;
};