Java 如何在 Selenium WebDriver 中使用 xPath 来抓取 SVG 元素?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/31520642/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-11 11:11:40  来源:igfitidea点击:

How to use xPath in Selenium WebDriver to grab SVG elements?

javaseleniumxpathsvg

提问by joaorodr84

I am testing an API, based on OpenLayers, with Selenium WebDriver(Java version).

我正在OpenLayers使用 Selenium WebDriver(Java 版本)测试基于 的 API 。

I want to test a functionality that uses OpenLayers.Control.ModifyFeature. I want to click on drawn features (SVG), drag then and check if they are present, visible or hidden.

我想测试一个使用OpenLayers.Control.ModifyFeature的功能。我想单击绘制的特征 (SVG),然后拖动并检查它们是否存在、可见或隐藏。

I have drawn a polygon, and I have selected it. See the image below:

我画了一个多边形,我选择了它。见下图:

polygon_and_handles

多边形和句柄

The HTML of these SVG elements is here:

这些 SVG 元素的 HTML 在这里:

<svg id="OpenLayers_Layer_Vector_161_svgRoot" width="1235" height="495" viewBox="0 0 1235 495" style="display: block;">
    <g id="OpenLayers_Layer_Vector_161_root" transform="" style="visibility: visible;">
        <g id="OpenLayers_Layer_Vector_161_vroot">
            <path id="OpenLayers_Geometry_Polygon_200" d=" M 393.0000000000964,213.9999999999891 486.0000000003338,275.9999999997126 384.00000000036925,284.9999999994434 393.0000000000964,213.9999999999891 z" fill-rule="evenodd" fill="blue" fill-opacity="0.4" stroke="blue" stroke-opacity="1" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" stroke-dasharray="none" pointer-events="visiblePainted" cursor="pointer" />
            <circle id="OpenLayers_Geometry_Point_619" cx="439.50000000021464" cy="244.99999999985084" r="6" fill="#009900" fill-opacity="0.5" stroke="#ee9900" stroke-opacity="1" stroke-width="1" stroke-linecap="round" stroke-linejoin="round" stroke-dasharray="none" pointer-events="visiblePainted" cursor="inherit" />
            <circle id="OpenLayers_Geometry_Point_621" cx="435.00000000035106" cy="280.49999999958163" r="6" fill="#009900" fill-opacity="0.5" stroke="#ee9900" stroke-opacity="1" stroke-width="1" stroke-linecap="round" stroke-linejoin="round" stroke-dasharray="none" pointer-events="visiblePainted" cursor="inherit" />
            <circle id="OpenLayers_Geometry_Point_623" cx="388.50000000023283" cy="249.4999999997126" r="6" fill="#009900" fill-opacity="0.5" stroke="#ee9900" stroke-opacity="1" stroke-width="1" stroke-linecap="round" stroke-linejoin="round" stroke-dasharray="none" pointer-events="visiblePainted" cursor="inherit" />
            <circle id="OpenLayers_Geometry_Point_202" cx="393.0000000000964" cy="213.9999999999891" r="6" fill="#990000" fill-opacity="1" stroke="#ee9900" stroke-opacity="1" stroke-width="1" stroke-linecap="round" stroke-linejoin="round" stroke-dasharray="none" pointer-events="visiblePainted" cursor="inherit" />
            <circle id="OpenLayers_Geometry_Point_203" cx="486.0000000003338" cy="275.9999999997126" r="6" fill="#990000" fill-opacity="1" stroke="#ee9900" stroke-opacity="1" stroke-width="1" stroke-linecap="round" stroke-linejoin="round" stroke-dasharray="none" pointer-events="visiblePainted" cursor="inherit" />
            <circle id="OpenLayers_Geometry_Point_204" cx="384.00000000036925" cy="284.9999999994434" r="6" fill="#990000" fill-opacity="1" stroke="#ee9900" stroke-opacity="1" stroke-width="1" stroke-linecap="round" stroke-linejoin="round" stroke-dasharray="none" pointer-events="visiblePainted" cursor="inherit" />
        </g>
        <g id="OpenLayers_Layer_Vector_161_troot" />
    </g>
</svg>

Suppose I want to select the red points.

假设我要选择红点。

I did this:

我这样做了:

String xpath = "//circle[contains(@id, 'OpenLayers_Geometry_Point') AND fill = '#990000']";
List<WebElement> vertices = driver.findElements(By.xpath(xpath));

But it always returns an empty list [].

但它总是返回一个空列表[]

What am I doing wrong here? Could anybody help me, please?

我在这里做错了什么?有人可以帮我吗?

Thanks a lot.

非常感谢。

EDIT 1 - Function: verticesAreVisible

编辑 1 - 功能:verticesAreVisible

Before the clicking actions, I want to get the elements and check if they are visible. I am using this function.

在单击操作之前,我想获取元素并检查它们是否可见。我正在使用这个功能。

public static boolean verticesAreVisible(WebDriver driver, String xpath) {
    List<WebElement> list = driver.findElements(By.xpath(xpath));
    if (list.isEmpty()) {
        return false;
    }
    boolean visible = true;
    for (int i = 0; i < list.size(); i++) {
        visible = visible && list.get(i).isDisplayed();
    }
    return !verticesAreNotVisible(driver) && visible;
}

EDIT 2 - Correct xPath

编辑 2 - 正确的 xPath

// This solution from Razib is valid if the SVG is on the root node
String xpath = "/*[name()='svg']/*[name()='circle']";
// I changed it so that any descendant is valid "//"
String xpath = "//*[name()='svg']//*[name()='circle']";
// Since I wanted only the red vertices, I added this
String xpath = "//*[name()='svg']//*[name()='circle' and @fill='#990000']";

采纳答案by Razib

May be you need to use the Actions with nameattribute in Xpath. In your XPath use it -

可能您需要nameXpath. 在您的 XPath 中使用它 -

"/*[name()='svg']/*[name()='SVG OBJECT']"  

Then try the following code snippet -

然后尝试以下代码片段 -

WebElement svgObj = driver.findElement(By.xpath(XPATH));
Actions actionBuilder = new Actions(driver);
actionBuilder.click(svgObj).build().perform();

回答by peetya

Try @fillinstead of filland OpenLayers_Geometry_Pointinstead of OpenLayers.Geometry.Point.

尝试@fill代替fillOpenLayers_Geometry_Point代替OpenLayers.Geometry.Point

回答by LoveLovelyJava one

To get just visibile elements you can use:

要获得可见元素,您可以使用:

wait = new WebDriverWait(driver, 5);
wait.until(ExpectedConditions.visibilityOfAllElementsLocatedBy(By.xpath("bla bla")));

回答by shiv

We also faced the similar issue in one of the screens where we have SVG implementation, I resolved using action class.

我们在其中一个有 SVG 实现的屏幕中也遇到了类似的问题,我使用 action 类解决了这个问题。

Action Class Package :
java.lang.Object
org.openqa.selenium.interactions.Actions

Sample Code :

示例代码:

WebElement svgObject= driver.findElement(By.xpath(XPATH));
Actions actionBuilderObj = new Actions(driver);
actionBuilderObj .click(svgObject).build().perform();

回答by Manideep Reddy

Tried with all sort of techniques to dive Inn but atlast I found out an easy way to handle this situation. When your desired svg doesnt have name and proper xpath changes dynamically then I used "cssSelector"

尝试了各种技术潜入旅馆,但最终我找到了一种简单的方法来处理这种情况。当您想要的 svg 没有名称并且正确的 xpath 动态更改时,我使用了“cssSelector”

WebElement DesiredSvg = driver.findElement(By.cssSelector("#scrollable-auto-tabpanel-0 > div > div > form > div:nth-child(1) > div:nth-child(1) > div > div > div.jss10127 > div > div.jss11602 > svg:nth-child(3)"));

DesiredSvg.click();