Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there an "if -then - else " statement in XPath?

It seems with all the rich amount of function in xpath that you could do an "if" . However , my engine keeps insisting "there is no such function" , and I hardly find any documentation on the web (I found some dubious sources , but the syntax they had didn't work)

I need to remove ':' from the end of a string (if exist), so I wanted to do this:

if (fn:ends-with(//div [@id='head']/text(),': '))             then (fn:substring-before(//div [@id='head']/text(),': ') )             else (//div [@id='head']/text()) 

Any advice?

like image 890
Yossale Avatar asked Jun 09 '09 16:06

Yossale


People also ask

How do you write conditional XPath expression?

To define an XPath expression that checks if a string element is empty, you must use the operator != . This example shows how to define an XPath expression that evaluates to true when a repeating element, which is referred to as a sequence, is empty. The effective Boolean value of an empty sequence is false.

What is the meaning of '/' in XPath?

Single Slash “/” – Single slash is used to create Xpath with absolute path i.e. the xpath would be created to start selection from the document node/start node.

Can we use and condition in XPath?

Using OR & AND In the below XPath expression, it identifies the elements whose single or both conditions are true. Highlight both elements as 'First Name' element having attribute 'id' and 'Last Name' element having attribute 'name'. In AND expression, two conditions are used.


1 Answers

Yes, there is a way to do it in XPath 1.0:

 concat(   substring($s1, 1, number($condition)      * string-length($s1)),   substring($s2, 1, number(not($condition)) * string-length($s2)) ) 

This relies on the concatenation of two mutually exclusive strings, the first one being empty if the condition is false (0 * string-length(...)), the second one being empty if the condition is true. This is called "Becker's method", attributed to Oliver Becker (original link is now dead, the web archive has a copy).

In your case:

 concat(   substring(     substring-before(//div[@id='head']/text(), ': '),     1,      number(       ends-with(//div[@id='head']/text(), ': ')     )     * string-length(substring-before(//div [@id='head']/text(), ': '))   ),   substring(     //div[@id='head']/text(),      1,      number(not(       ends-with(//div[@id='head']/text(), ': ')     ))     * string-length(//div[@id='head']/text())   ) ) 

Though I would try to get rid of all the "//" before.

Also, there is the possibility that //div[@id='head'] returns more than one node.
Just be aware of that — using //div[@id='head'][1] is more defensive.

like image 183
Tomalak Avatar answered Oct 04 '22 02:10

Tomalak