我正在使用Selenium Webdriver (ver 2.31.2.0)
(。Net),我正在尝试提取从`driver.PageSource'返回的元素(XML)。
我的问题:如何使用以下xpath获取项目列表。 我可以使用XPATH插件在FF中播放,但相同的代码在Selenium Webdriver中不起作用
任何帮助?
这是我在Selenium Webdriver中的代码:
var driver = new FirefoxDriver();
driver.Navigate().GoToUrl("http://website_name/languages.xml");
string _page_source = driver.PageSource;
ReadOnlyCollection<IWebElement> webElements = _page_source.FindElementsByXPath("//response//results//items/vList");
我的xml看起来像这样:
<response xmlns="http://schemas.datacontract.org/2004/07/myproj.cnn.com">
xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
<meta>
</meta>
<results i:type="vList">
<name>Language</name>
<queryValue>language</queryValue>
<displayOrder>0</displayOrder>
<items>
<vList>
<name>English</name>
<displayName>English</displayName>
<displayOrder>0</displayOrder>
<items />
</vList>
<vList>
<name>Swedish</name>
<displayName>Swedish</displayName>
<displayOrder>1</displayOrder>
<items />
</vList>
</items>
</results>
</response>
答案 0 :(得分:4)
您可以使用selenium浏览并获取xml,但可以使用.net类使用xml。
driver.PageSource
属性是一个字符串,您应该直接使用.Net类来解析所表示的xml。此外,字符串对象上没有方法FindElementsByXPath()
,除非这是您编写的扩展方法。
使用selenium的driver.PageSource
var driver = new FirefoxDriver();
driver.Navigate().GoToUrl("http://website_name/languages.xml");
XmlReader reader = XmlReader.Create(driver.PageSource);
或者,通过使用
直接浏览到网址来阅读xmlXmlReader reader = XmlReader.Create("http://website_name/languages.xml");
然后使用下面的代码来解析和读取xml。 需要注意的关键点是如何将命名空间信息提供给xpath。
//load xml document
XElement xmlDocumentRoot = XElement.Load(reader);
//also add the namespace infn, chose a prefix for the default namespace
XmlNameTable nameTable = reader.NameTable;
XmlNamespaceManager namespaceManager = new XmlNamespaceManager(nameTable);
namespaceManager.AddNamespace("a", "http://schemas.datacontract.org/2004/07/myproj.cnn.com");
//now query with your xml - remeber to prefix the default namespace
var items = xmlDocumentRoot.XPathSelectElements("//a:results/a:items/a:vList", namespaceManager);
Console.WriteLine("vlist has {0} items.", items.Count());
foreach (var item in items)
{
Console.WriteLine("Display name: {0}", item.XPathSelectElement("a:displayName",namespaceManager).Value);
}
// OR get a list of all display names using linq
var displayNames = items.Select(x => x.XPathSelectElement("a:displayName", namespaceManager).Value).ToList();
您需要以下命名空间才能实现上述功能:
using System;
using System.Linq;
using System.Xml;
using System.Xml.Linq;
using System.Xml.XPath;
答案 1 :(得分:1)
您发布的XML输入声明了一个名称空间:xmlns="http://schemas.datacontract.org/2004/07/myproj.cnn.com"
。见下一行:
<response xmlns="http://schemas.datacontract.org/2004/07/myproj.cnn.com">
因为此命名空间没有前缀,所以它是没有前缀的所有元素的默认命名空间。这意味着元素<response>
和元素<results>
等都属于此命名空间。
请阅读下一篇:http://www.w3schools.com/xml/xml_namespaces.asp
因此,在您的代码中,您需要在任何XPath评估工作之前声明命名空间。我不知道如何在Selenium Webdriver中设置命名空间,但你可以找到它。
一旦声明了命名空间,就需要在XPath中使用它。例如,在XSLT中,您可以按如下方式声明命名空间:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:foo="http://schemas.datacontract.org/2004/07/myproj.cnn.com">
我现在使用前缀foo
声明了名称空间。可用于检索所有vList
元素的XPath将是:
/foo:response/foo:results/foo:items/foo:vList
要获取您可以使用的所有displayName
元素:
/foo:response/foo:results/foo:items/foo:vList/foo:displayName
如果你想要元素的总数而不是元素列表,你可以在它周围包裹count()
,如:
count(/foo:response/foo:results/foo:items/foo:vList)
count(/foo:response/foo:results/foo:items/foo:vList/foo:displayName)
你使用的XPath中有很多//
。如果确实有必要,请仅使用//
,因为如果您已知道路径,它将扫描整个文件并获取所需的更多资源。