I have firexpath, and it doesn't seem to be working with xpath. Even something simple //div returns no results. Even if I click on an existing node, say "copy XPath" and then paste that XPath into filter input box, it says "no nodes found". //*[name()='div'] does work though. Am I missing a namespace or something? Here is what root tag looks like (it's a valid XHTML):
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-us" class="ff ff3">
I didn't find a support forum for FireXPath, so I'm posting it here.
In case you cannot register a namespace (for the default namespace) and then prefix every element name in the XPath expression with the registered prefix, then you can use an XPath expression like this:
/*[name()='x']/*[name()='y']/*[name()='z']
In case there are elements belonging to other namespaces (than the default namespace), you'll have to use a more specific XPath expression:
/*[name()='x' and namespace-uri()='http://www.w3.org/1999/xhtml']
/*[name()='y' and namespace-uri()='http://www.w3.org/1999/xhtml']
/*[name()='z' and namespace-uri()='http://www.w3.org/1999/xhtml']
If you could have registered the default namespace and the prefix was (say) "p", then the above would be equivalent to a now simpler expression:
/p:x/p:y/p:z
I have not used firexpath but it looks as though the default namespace xmlns="http://www.w3.org/1999/xhtml" is preventing xpath from finding the div as the div element inside the element which defies xmlns with be prefixed with that namespace.
You therefore would need to register the namespace with firexpath using some sort of method call??? then //div should work or your expression is fine as well, if you were wanting to consider namespaces in the expression you could include a check for the namespace like so
//*[name()='div' and namespace-uri()='http://www.w3.org/1999/xhtml']
EDIT:
I have downloaded firexpath which now is called firepath and it doesn't look possible to register a namespace so it looks like you will have to the name() method
Related
Using xslt 1.0 (BizTalk 2016) I'm looking for a generic way to select the namespace of any valid xml document
For example, I have the following xml document:
<?xml version="1.0" encoding="utf-8"?>
<PortfolioActivation xmlns="http://www.random.com/bo/request/portfolioactivation">
<Portfolio>
<ExternalId>PRT-00000450</ExternalId>
<InternalId>c8b0239c-1e98-e911-a8b1-00224800449b</InternalId>
<Version>8627558</Version>
<Type>001</Type>
</Portfolio>
</PortfolioActivation>
Given that the Root element value could be anything, what would be the xpath to select the value of the namespace i.e http://www.random.com/bo/request/portfolioactivation
I had hoped "/*/#xmlns" would work but it doesn't.
The namespace of the outermost element can be found using namespace-uri(/*).
Alternatively, the default namespace that's in scope for the outermost element is /*/namespace::*[name()=''].
These aren't the same thing. Consider
<p:root xmlns="a.ns" xmlns:p="b.ns"/>
The first expression will give you "b.ns", the second will give you "a.ns". It's not clear from your question which you want.
Note that namespaces are not attributes in the XDM data model, so you never access them using the attribute axis. #xmlns will therefore never work.
I have the following XML:
<envelope>
<action>INSERT</action>
<auditId>123</auditId>
<payload class="vendor">
<fizz buzz="3"/>
</payload>
</envelope>
I am trying to write an XPath expression that will pluck out vendor (value for the payload's class attribute) or whatever its value is.
My best attempts are:
/dataEnvelope/payload[#class="vendor"]#class
But this requires the expression to already know that vendor is the value of the attribute. But if the XML is:
<dataEnvelope>
<action>INSERT</action>
<auditId>123</auditId>
<payload class="foobar">
<fizz buzz="3"/>
</payload>
</dataEnvelope>
Then I want the expression to pluck out the foobar. Any ideas where I'm going awry?
If you need #class value from payload node, you can use
/dataEnvelope/payload[#class]/#class
or just
/dataEnvelope/payload/#class
At first, your two XML files are out-of-sync - one references envelope and the other references dataEnvelope. So exchange one for the other, if necessary.
So, to get the attribute value of payload, you can use an XPath expression like this which uses a child's attribute value to be more specific:
/envelope/payload[fizz[#buzz='3']]/#class
Output is:
vendor
If the document element can/will change, then you can keep the XPath more generic and select the value of the class attribute from the payload element that is a child of any element:
/*/payload/#class
If you know that it will always be a child of envelope, then this would be more specific(but the above would still work):
/envelope/payload/#class
<?xml version="1.0" encoding="UTF-8"?>
<serviceOfferings xmlns="http://www.abc.com/aaa" xmlns:ns2="http://www.w3.org/2005/Atom">
<serviceOffering type="provider">
<links>
<link title="Service Provider" type="application/xml" rel="self" href="https://www.yahoo.com"/>
<link rel="create" href="https://www.google.com/create"/>
</links>
</serviceOffering>
</serviceOfferings>
How do I get the href value for the link which attribute rel is create
The target element is in a default namespace. First, you'll need to register that namespace with your XPath engine. How you do this depends on the tool you're using, which means it's outside the scope of this question (since you haven't told us how you're evaluting your expressions).
Let's assume you've registered the namespace to a prefix called aaa. Select the desired link like this:
//aaa:link[#rel='create']
Or, more specifically:
/*/*/*/aaa:link[#rel='create']
For completeness, in most cases this can also be achieved without registering a namespace, at the cost of reduced readability:
/*/*/*/*[name()='link' and #rel='create']
This selects all elements whose name is "link" (regardless of the namespace they belong to) and that have a rel attribute whose string value is "create", and that are grand-grand-children of the top element of the XML document.
I want to capture all search result links (search engine: http://search.yahoo.com) and summary from the result page. ClassName of Link is 'yschttl spt' and className for summary is 'abstr'
Source Code Looks like below for Link and summary.
Link:
<a id="yui_3_3_0_1_1301085039901361" dirtyhref="http://search.yahoo.com/r/_ylt=A0oG7m9u.4xNvWYA7N5XNyoA;_ylu=X3oDMTE2ZXNhNjRzBHNlYwNzcgRwb3MDMgRjb2xvA2FjMgR2dGlkA01TWUMwMDFfMTc5/SIG=11stois8r/EXP=1301106638/**http%3a//en.wikipedia.org/wiki/Pune,_India" class="yschttl spt" href="http://search.yahoo.com/r/_ylt=A0oG7m9u.4xNvWYA7N5XNyoA;_ylu=X3oDMTE2ZXNhNjRzBHNlYwNzcgRwb3MDMgRjb2xvA2FjMgR2dGlkA01TWUMwMDFfMTc5/SIG=11stois8r/EXP=1301106638/**http%3a//en.wikipedia.org/wiki/Pune,_India" data-bns="API" data-bk="5096.1"><b>Pune</b> - Wikipedia, the free encyclopedia</a>`
Summary Div:
<div id="yui_3_3_0_1_1301085039901338" class="abstr"><b id="yui_3_3_0_1_1301085039901337">Pune</b> is undoubtedly a great place to eat. Fergusson <b id="yui_3_3_0_1_1301085039901352">College</b> <b>Road</b> is full of budget eateries serving delicous hot food at nominal charges. For a range of multi-cuisine ...</div>
I am using below line of code to capture both (link and summary).
final List<WebElement> links = driver.findElements(By.className("yschttl spt"));
final List<WebElement> linksSummary = driver.findElements(By.className("abstr"));
But now working at all.
I also tried using below XPaths for Link:
//a[starts-with(#id, 'yui_')]
//a[#data-bns='API']
I cannot use ID as whole because that ID number is not same for all search result links.
Nothing is working. Please help.
thanks in advance.
The main problem is that you are not correctly asking for a classname. The instance of class="yschttl spt" says that the element may be identified by two class names, yschttl or spt. It does not say that the classname is yschttl spt so asking for By.className("yschttl spt") will always fail.
Note that the reason the XPath suggested by #Tarun works is that XPath has no notion of what an HTML class name is or should be. In XPath, #class simply specifies the name of an attribute--with no underlying semantics.
Further, note that a class name may not contain spaces. For more details about specifying class names, see the HTML class attribute specification.
I don't use selenium 2.0 but when I tried //a[#class='yschttl spt'] in Firefox XPath Checker, I got to see all 10 results in page. I am soon to begin with Selenium 2.0, may be I could try then...
I'm using Nokogiri::XML to parse responses from Amazon SimpleDB. The response is something like:
<SelectResponse xmlns="http://sdb.amazonaws.com/doc/2007-11-07/">
<SelectResult>
<Item>
<Attribute><Name>Foo</Name><Value>42</Value></Attribute>
<Attribute><Name>Bar</Name><Value>XYZ</Value></Attribute>
</Item>
</SelectResult>
</SelectResponse>
If I just hand the response straight over to Nokogiri, all XPath queries (e.g. doc/"//Item/Attribute[Name='Foo']/Value") return an empty array. But if I remove the xmlns attribute from the SelectResponse tag, it works perfectly.
Is there some extra thing I need to do to account for the namespace declaration? This workaround feels horribly like a hack.
That XPath query looks for elements that are not in any namespace. You need to tell your XPath processor that you are looking for elements in the http://sdb.amazonaws.com/doc/2007-11-07/ namespace.
One way to do that with Nokogiri is:
doc = Nokogiri::XML.parse(...)
doc.xpath("//aws:Item/aws:Attribute[Name='Foo']/aws:Value", {"aws" => "http://sdb.amazonaws.com/doc/2007-11-07/"})
I found "Namespaces in XML" really helpful in understanding what's going on.
Basically if you have a namespace defined via xmlns=, you must use a namespace in your XPath searches.
So in your case, you could do one of three things:
Remove the xmlns attribute from the root SearchResponse. In that case your original, namespace-less XPath query will work.
Use the default namespace in your XPath query:
doc/"//xmlns:Item/xmlns:Attribute[xmlns:Name='Foo']/xmlns:Value"
Define a custom namespace in the second argument of the xpath method and use that in your query, as shown in hrnt's solution above.