Reputation: 17553
I am looking into the XPath Axes and I am able to understand all below axes
'ancestor'
| 'ancestor-or-self'
| 'attribute'
| 'child'
| 'descendant'
| 'descendant-or-self'
| 'following'
| 'following-sibling'
| 'parent'
| 'preceding'
| 'preceding-sibling'
| 'self'
The only axes I am not able to understand is
| 'namespace'
Can anyone give me a good example and understanding about what 'namespace' actually do?
Example:-
Open :- https://www.google.co.in/
OR
HTML code
<a style="left:-1000em;position:absolute" href="/setprefs?suggon=2&prev=https://www.google.co.in/&sig=0_ujdR1PrGxEbi_EiD6RbIb4VvaXc%3D">Screen-reader users, click here to turn off Google Instant.</a>
I am trying the below xpath
//a[@style='left:-1000em;position:absolute']/namespace::*[name()='google']
What is wrong I am doing in above namespace?
In addition I also want to know about that what is the use of axes | 'attribute'. where and in which situation it is helpful
Upvotes: 3
Views: 2764
Reputation: 884
According to the logic, it should select all elements associated with the namespace. However, its behavior is a bit more complicated, hence it is not used often. (It is considered as deprecated in XPath 2.0.)
<?xml version="1.0" encoding="UTF-8"?>
<ROOT>
<BASE xmlns:base="http://www.tei-c.org/ns/1.0" xmlns:dc="http://purl.org/dc/elements/1.1/">
<base:p>XXX</base:p>
<dc:p>yyy</dc:p>
</BASE>
<NEXT xmlns="http://purl.org/dc/elements/1.1/">
<p>zzz</p>
</NEXT>
</ROOT>
XPath (2.0):
//*[namespace::dc]
selects the whole BASE
element. It is similar to:
//*[namespace-uri-for-prefix('dc', .)]
which does not work in XPath 1.0.
//*[namespace::*='http://purl.org/dc/elements/1.1/']
selects both, BASE
as well as NEXT
elements. Such a usage is considered a bit strange and it is not recommended.
//*[local-name(.) eq 'p' and namespace::*='http://purl.org/dc/elements/1.1/']
selects all p
elements, which means base:p
, dc:p
, p
as well.
//*[local-name(.) eq 'p' and namespace::dc]
selects base:p
and dc:p
of the BASE
element.
//*[local-name(.) eq 'p' and namespace-uri() eq 'http://purl.org/dc/elements/1.1/']
selects all elements bounded to the URI. It means it is the most accurate option.
Or it is possible to try something like:
//*[contains(namespace-uri(), 'purl')]
or
//self::BASE/*[contains(namespace-uri(), 'purl')]
Tested in Oxygen Author 17.1
UPDATE
As for your need, it seems you are probably trying to select an element with the string google
in the href
attribute, not with a particular namespace. What about //a[contains(@href, 'google')]
?
UPDATE II
As stated in comments, the UPDATE was the working solution. However, I think the next information is also useful:
Upvotes: 2
Reputation: 89295
namespace::
axis selects namespace nodes. Nothing fancy.
And namespace nodes, according to the linked specs includes :
every attribute on the element whose name starts with xmlns:
every attribute on an ancestor element whose name starts xmlns:
unless the element itself or a nearer ancestor redeclares the prefix
an xmlns
attribute, if the element or some ancestor has an xmlns
attribute, and the value of the xmlns
attribute for the nearest such element is non-empty
For example, given the following XML element :
<a xmlns:google="some namespace uri here"/>
XPath expression below will return the xmlns:google
attribute [demo]. :
//a/namespace::*[name()='google']
This example corresponds to the first bullet point mentioned above, since xmlns:google
is attribute, on the context element <a>
, whose name starts with xmlns:
.
Similar explanation goes for attribute
axis; it simply selects XML attributes.
You can consider attribute
axis as a longer version of @
which you've already been using. For example, the two expressions below mean the same :
//a[attribute::style='left:-1000em;position:absolute']
//a[@style='left:-1000em;position:absolute']
Upvotes: 4