I am trying get the first and second <td> in all the <tr> from this table with XPath. But something I am doing wrong. Return [INVALID XPATH EXPRESSION]
//table[#id='thetable']/tbody/tr/concat(td[1],'-',td[2])
Try:
string-join(//table[#id='thetable']/tbody/tr/td[1 to 2]/string(), "-")
Using concat() on the right hand side of "/" requires an XPath 2.0 engine. The error message suggests you are trying to run this using an XPath 1.0 engine. The string-join version also needs XPath 2.0.
In fact any expression that returns a sequence of strings is going to need XPath 2.0 because the XPath 1.0 type system doesn't have any such data type.
If you want an XPath 2.0 implementation that runs in the browser you could try Saxon-JS. (In fact that will give you XPath 3.1).
Related
I got this xpath
//td[#id='datepicker-54143-1002-23']/button/span
The numbers 54142-1002 will change. 23 is the date. How can I use contains to make the xpath? So I would like to make the xpath contain datepicker and 23 in this case.
You can try
//td[starts-with(#id, 'datepicker-') and ends-with(#id, '-23')]/button/span
But note that ends-with available from XPath version 2.0
If ends-with doesn't work for you, as #JaSON suggested in his answer, it's because you're using XPATH 1.0, and ends-with is available only in XPATH 2.0.
Try this instead:
//td[starts-with(#id,'datepicker-') and substring(#id,string-length(#id)-2)='-23']
Please note that if "23" changes to string of different length you'll have to adjust "-2" part accordingly.
Using XPath 1.0 want to get list of text nodes applying XPath 'substring' function on every text node
substring(//p/text(), 10)
gives only one first text's sub-string, when
//p/text()
gives all of them, but want all sub-strings as set
EDIT:
Tried
//p/substring(text(), 10)
Says invalid XPath expression
How can I achieve this ?
Thanks in advance
If you want a set of strings as the result of an XPath 1.0 expression, then you're out of luck, because there is no such data type in XPath 1.0: the only collections available are collections of nodes, and you can only select nodes that already exist, you can't create new ones.
With XPath 2.0 this is a piece of cake:
//p/text()/substring(., 10)
So if you possibly can, find yourself an XPath 2.0 processor.
I am try to test if a parser support XPath 2.o. Can someone give me some basic XPath 2.o expression which will pass if the parser support XPath 2.o and will fail if the parser only support 1.0.
Do not have to be fancy strings, just 4-5 basic XPath expressions.
XSLT provides system-property('xsl:version') for identifying version information. Unfortunately, XPath has no such function to distinguish between XPath 1.0 vs XPath 2.0. You can probe the library by calling a function that's only defined in XPath 2.0 and see if it fails. Here are a few such functions:
current-dateTime()
lower-case(), upper-case(), ends-with()
matches(), replace(), tokenize()
Wikipedia has a more extensive list of library XPath functions, grouped by category, and marked per XPath 1.0 vs XPath 2.0.
The simplest I can think of are
()
1 eq 1
abs(3)
''''
*:x
My problem using XPath is whenever i use the "substring" function I get only one match and I want to get them all.
another problem is whenever I use the combination of "substring" and operator | it just won't work (no matches).
For example: http://www.tripadvisor.com/Hotel_Review-g52024-d653910-Reviews-Ace_Hotel_Portland-Portland_Oregon.html
on this webpage I used the query
//SPAN[#class='ratingDate relativeDate']/#title | //*[#class='ratingDate']/text()
I got 10 matches but some of them start with "Reviewed ". so I added "substring-after"
and didn't get any matches
the original syntax:
//SPAN[#class='ratingDate relativeDate']/#title | substring-after(//*[#class='ratingDate']/text(), 'Reviewed ')
With pure XPath 1.0 you can't solve that, if you use XPath 2.0 or XQuery 1.0 you can put the substring-after call into the last step of the path e.g. //*[#class='ratingDate']/substring-after(., 'REVIEWED').
If you only have XPath 1.0 then you first need to select the elements with XPath and then iterate over the result in your host language to extract the substring for each element; how you do that depends on the host language and the XPath API.
I want to write xpath to check node contain '#'
<node1>
<node11>Some text</node11>
<node11>#2o11 PickMe</node12>
</node1>
I want to write xpath like "//node11[contains(,'#\d+')]". Whats correct way to check #
The correct XPath expression is:
//node11[contains(., '#')]
In your XML, the closing tag of the second subnote should be </node11> instead of </node12>.
If you are using xpath 2.0 you should be able to use something like:
"//node11[matches(.,'#\d+')]"
However, if you aren't using 2.0 you won't have regex support directly. If you are using 1.0 then you won't be able to match using \d+. But this will work:
"//node11[contains(.,'#')]"
Or even:
"//node11[starts-with(.,'#')]"
Use:
/*/node11[contains(., '#')]
Note: It is recommended to avoid using the // pseudo-operator because this most often leads to very slow evaluation of the XPath expression.