I'm using Selenium Webdriver (ver 2.31.2.0) (.Net) and I'm trying to extract an element (XML) which is returning from the `driver.PageSource'.
My Question: How to get the list of items using the below xpath.
I able to play in FF using XPATH addons but the same code does not work in Selenium Webdriver
any help?
Here is my code in 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");
my xml looks like this:
<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>
You can use selenium to browse to and obtain the xml, but work with the xml using .net classes.
The driver.PageSource property is a string, and you should use .Net classes directly to parse the xml represented. Also, there is no method FindElementsByXPath() on a string object, unless this is an extension method that you have written.
Read the xml using the driver.PageSource from selenium
var driver = new FirefoxDriver();
driver.Navigate().GoToUrl("http://website_name/languages.xml");
XmlReader reader = XmlReader.Create(driver.PageSource);
Or, read the xml by directly browsing to the url using
XmlReader reader = XmlReader.Create("http://website_name/languages.xml");
And then use below code to parse and read the xml.
Key point to note is how the namespace information is provided to the 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();
You will need the following namespaces for the above to work:
using System;
using System.Linq;
using System.Xml;
using System.Xml.Linq;
using System.Xml.XPath;
The XML input you have posted has a namespace declared: xmlns="http://schemas.datacontract.org/2004/07/myproj.cnn.com". See the next line:
<response xmlns="http://schemas.datacontract.org/2004/07/myproj.cnn.com">
Because this namespace has no prefix it is the default namespace for all elements without a prefix. Which means element <response> and element <results> etc all belong to this namespace.
Read next: http://www.w3schools.com/xml/xml_namespaces.asp
So in you code you need to declare the namespace before any XPath evaluation will work. I do not know how to set the namespace in Selenium Webdriver but you can find it I guess.
Once you declared the namespace you need to use this in your XPath. For example in a XSLT you can declare the namespace as follows:
<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">
I now declared the namespace with prefix foo. The XPath that can be used to retrieve all vList elements would be:
/foo:response/foo:results/foo:items/foo:vList
To get all displayName elements you can use:
/foo:response/foo:results/foo:items/foo:vList/foo:displayName
If you want the total count of the elements instead of the list of elements, you can wrap count() around it like:
count(/foo:response/foo:results/foo:items/foo:vList)
count(/foo:response/foo:results/foo:items/foo:vList/foo:displayName)
The XPath you used has a lot of // in it. Only use // if it is really necessary, because it will scan the complete file and takes more resources than necessary if you know the path already.
Related
I have a pretty massive iOS Framework to bind.
This framework depends on two others.
I created the binding project, successfully generated the ApiDefinitions.cs file and StructsAndEnums.cs. So far so good.
Now, when I try to build it in Debug mode, I get about 30+ errors regarding syntax issues in temporary files.
These errors only occur in Trampolines.g.cs, and SupportDelegates.g.cs files.
The worst of the two is the SupportDelegates.g.cs file which looks like this :
//
// Auto-generated from generator.cs, do not edit
//
// We keep references to objects, so warning 414 is expected
#pragma warning disable 414
using System;
using System.Drawing;
using System.Diagnostics;
using System.ComponentModel;
using System.Threading.Tasks;
using System.Runtime.InteropServices;
using System.Runtime.CompilerServices;
using UIKit;
using GLKit;
using Metal;
using MapKit;
using Photos;
using ModelIO;
using SceneKit;
using Contacts;
using Security;
using Messages;
using AudioUnit;
using CoreVideo;
using CoreMedia;
using QuickLook;
using CoreImage;
using SpriteKit;
using Foundation;
using CoreMotion;
using ObjCRuntime;
using AddressBook;
using MediaPlayer;
using GameplayKit;
using CoreGraphics;
using CoreLocation;
using AVFoundation;
using NewsstandKit;
using FileProvider;
using CoreAnimation;
using CoreFoundation;
namespace System.Action`1[[Foundation.NSString, Xamarin.iOS, Version=0.0.0 {
public delegate void 0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065]] (NSString obj);
}
The Trampolines.g.cs file is generating almost completely, but the same kind of issue appears in the middle of the generated C# code:
static internal class SDActionArity2V1 {
static internal readonly DActionArity2V1 Handler = Invoke;
[MonoPInvokeCallback (typeof (DActionArity2V1))]
static unsafe void Invoke (IntPtr block, IntPtr arg1, IntPtr arg2) {
var descriptor = (BlockLiteral *) block;
var del = (global::System.Action<NSString, global::System.Action<NSString>>) (descriptor->Target);
if (del != null)
del ( Runtime.GetNSObject<NSString> (arg1), (System.Action`1[Foundation.NSString]) Marshal.GetDelegateForFunctionPointer (arg2, typeof (System.Action`1[Foundation.NSString])));
}
}
Some other binding projects is generating the same kind of files, and eveything seems to be working fine, so I'm actually struggling to find the root cause of this.
Any ideas ?
EDIT:
To give more infos here is the generated interface definition
https://gist.github.com/Miiite/367e17335431e932acdc92c65b504bd4
EDIT2: Here is what sharpie generated as log output
https://gist.github.com/Miiite/e272622df2e853d53f1add4c8eb4eabf
I believe the issue is here:
void PresentCheckoutForSubmittingTransactionCompletionHandler(Action<OPPTransaction, NSError> completionHandler, [NullAllowed] Action<NSString, Action<NSString>> paymentBrandSelectedHandler, [NullAllowed] Action cancelHandler);
I think the Action inside the Action is causing the problem, the generator might not support this, so you might need to find a different way of binding that.
This problematic method can definitely be bound, if you need it here is how (I omitted the rest of the class members for brevity):
delegate void OPPPaymentBrandSelectedHandler (string paymentBrand, [BlockCallback] OPPPaymentCompletionHandler completionHandler);
delegate void OPPPaymentCompletionHandler ([NullAllowed] string checkoutId);
[BaseType (typeof (NSObject))]
interface OPPCheckoutProvider {
// -(void)presentCheckoutForSubmittingTransactionCompletionHandler:(void (^ _Nonnull)(OPPTransaction * _Nullable, NSError * _Nullable))completionHandler
// paymentBrandSelectedHandler:(void (^ _Nullable)(NSString * _Nonnull, void (^ _Nonnull)(NSString * _Nullable)))paymentBrandSelectedHandler
// cancelHandler:(void (^ _Nullable)(void))cancelHandler;
[Export("presentCheckoutForSubmittingTransactionCompletionHandler:paymentBrandSelectedHandler:cancelHandler:")]
void PresentCheckoutForSubmittingTransactionCompletionHandler(Action<OPPTransaction, NSError> completionHandler, [NullAllowed] OPPPaymentBrandSelectedHandler paymentBrandSelectedHandler, [NullAllowed] Action cancelHandler);
}
The trick is to instead of using nested Actions you need to break it into two delegates and use the BlockCallback attribute to instruct the generator that the parameter should be marshaled as an ObjC block, then just use the parent delegate as the type of the paymentBrandSelectedHandler parameter inside the PresentCheckoutForSubmittingTransactionCompletionHandler method.
Hope this helps to get you completely unblocked. That said we should report a much better error, I'll discuss with the team and have a look.
Cheers!
I am trying to use xpath in RFT. Searching over the net threw this code at me-
private static NodeList getNodesWithXPath(Document document, String xpathStr)
throws XPathExpressionException {
NodeList nodes = null;
XPathFactory factory = XPathFactory.newInstance();
XPath xpath = factory.newXPath();
if (xpathStr != null) {
XPathExpression expr = xpath.compile(xpathStr);
Object result = expr.evaluate(document, XPathConstants.NODESET);
nodes = (NodeList) result;
}
return nodes;
}
Now, I am new at RFT and totally at a loss about how to access the 'Document' object? Trying to typecast TestObject into this throws an exception. I could see a few examples stating something like
Document doc = parse(xmlFileLocation)
but I am not sure what this xmlFileLocation means. I have a simple web page where I need to identify the element using xpath.
P.S. - I understand there are other ways of identifying the object using atDescendant, etc, but I need to explicitly use xpath here due to some reasons.
Any help would be greatly appreciated.
Thanks!
They are different Document objects.
I think you got the code from IBM developerworks, and that is a document obtained from an XML file, thus browsable with XPATH.
RFT Document is com.rational.test.ft.object.interfaces.DocumentTestObject
while XML related one probably is org.w3c.dom.Document.
Totally different classes.
XPath is not supported by RFT and also no answers in the forums.
If you need XPath queries in your pages try something else, like Selenium.
I've searched and found this error all over the stackoverflow forum, but it applies differently each time and I'd like someone help me in this particular matter.
public IEnumerable<Project> FindRange(string filterExpression, string sortingExpression, int startIndex, int count)
{
try
{
using (BusinessContext context = new BusinessContext())
{
if (!String.IsNullOrWhiteSpace(filterExpression))
return context.Projects
.Where(filterExpression)
The last line being the one of the error...
Do you have any idea why is this happening? I've already added all the usings and dlls needed, being:
using System;
using System.Collections.Generic;
using System.Data.Entity;
using System.Linq;
What am I missing? I've got code structured the same way, working...
Your filterexpression parameter should not be a string - it should be a Func<>.
See http://msdn.microsoft.com/en-us/library/system.linq.enumerable.where(v=vs.100).aspx
It looks like you may be trying to use the Dynamic Linq library. In that case you need to ensure that you've added the NuGet package to your project and then include this namespace:
using System.Linq.Dynamic;
If your BusinessContext class has a string property such as Name that you are wanting to filter on then your where expression should look something like
.Where(x => x.Name.ToLower().StartsWith(filterExpression.ToLower()))
I'm developing a library of OData queries using Web Api and ODataController. When I go to run my api from a web browser it returns nothing. I don't get an error of any kind. I can debug in Visual Studio and see clearly that the method runs and successfully returns my results as an IQueryable<>. Somewhere under the hood it's discarding my data. Has anyone else seen or encountered this? I've included my code below for reference:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Web.Http;
using System.Web.Http.OData;
using Epm.Core.Model;
using System.Web.Http.OData.Query;
using Epm.Data.Access;
using Epm.Service.Assemblers;
namespace Epm.Service.Web.Controllers.OData
{
public class SearchActionsController : ODataController
{
private readonly EpmEntities context = new EpmEntities();
[Queryable(AllowedQueryOptions=AllowedQueryOptions.All)]
public IQueryable<ActionStepDisplay> Get(int planId, int? factorId, bool? showArchived)
{
var user = this.GetCurrentUser();
var results = (from p in context.SearchActions(user.SessionId, planId, factorId, showArchived, 1, null)
select p).ToModel().ToArray();
return results.AsQueryable();
}
protected override void Dispose(bool disposing)
{
context.Dispose();
base.Dispose(disposing);
}
}
}
My configuration:
ODataModelBuilder modelBuilder = new ODataConventionModelBuilder();
modelBuilder.EntitySet<Epm.Core.Model.ActionStep>("SearchActions");
Microsoft.Data.Edm.IEdmModel model = modelBuilder.GetEdmModel();
config.Routes.MapODataRoute("ODataRoute", "odata", model);
You are returning ActionStepDisplay from your method, but in builder you specified ActionStep as the entity.
May be Not Acceptable (406) in the response header
Possibly the problem lies with the MediaFormatter, which gets called after the controller has finished. When a media type formatter encounters a reference loop (where object A reference B and B references A) then you need to tell the media type formatter how to handle that, so in the Json Media Type Formatter you do something like...
json.SerializerSettings.PreserveReferencesHandling =
Newtonsoft.Json.PreserveReferencesHandling.All;
See Documentation Here
I'd recommend you use Fiddler to see what is actually going on. You say your not getting a response in the browser, so what HTTP code is returned? You can use Fiddler to find out...
There's some work in progress related to adding xpath support to jsoup https://github.com/jhy/jsoup/pull/80.
Is it working?
How can I use it?
JSoup doesn't support XPath yet, but you may try XSoup - "Jsoup with XPath".
Here's an example quoted from the projects Github site (link):
#Test
public void testSelect() {
String html = "<html><div><a href='https://github.com'>github.com</a></div>" +
"<table><tr><td>a</td><td>b</td></tr></table></html>";
Document document = Jsoup.parse(html);
String result = Xsoup.compile("//a/#href").evaluate(document).get();
Assert.assertEquals("https://github.com", result);
List<String> list = Xsoup.compile("//tr/td/text()").evaluate(document).list();
Assert.assertEquals("a", list.get(0));
Assert.assertEquals("b", list.get(1));
}
There you'll also find a list of features and expressions of XPath that are supported by XSoup.
Not yet,but the project JsoupXpath has make it.For example,
String html = "<html><body><script>console.log('aaaaa')</script><div class='test'>some body</div><div class='xiao'>Two</div></body></html>";
JXDocument underTest = JXDocument.create(html);
String xpath = "//div[contains(#class,'xiao')]/text()";
JXNode node = underTest.selNOne(xpath);
Assert.assertEquals("Two",node.asString());
By the way,it supports the complete W3C XPATH 1.0 standard syntax.Such as
//ul[#class='subject-list']/li[./div/div/span[#class='pl']/num()>(1000+90*(2*50))][last()][1]/div/h2/allText()
//ul[#class='subject-list']/li[not(contains(self::li/div/div/span[#class='pl']//text(),'14582'))]/div/h2//text()
HtmlUnit supports XPath. I've used this for certain projects and it works reasonably well.