tafit3
tafit3

Reputation: 550

What is the simplest syntax for Iverson bracket in XPath?

I would like to use Iverson bracket (ie. mapping true => 1, false => 0) in the XPath expression.

Example: instead of writing

someNumber+(if(elem1/elem2[@attr='123'])then(1)else(0)))*someOtherNumber

I would like to write (but somehow without the "Iverson")

someNumber+Iverson(elem1/elem2[@attr='123'])*someOtherNumber

The following doesn't work:

someNumber+[elem1/elem2[@attr='123']]*someOtherNumber

Casting to boolean works:

someNumber+boolean(elem1/elem2[@attr='123'])*someOtherNumber

Is there a more simple syntax than "if(...)then(1)else(0)" or "boolean(...)"?

Upvotes: 2

Views: 151

Answers (1)

Abel
Abel

Reputation: 57189

Iverson

Interestingly, in XPath you already use a version of the Iverson bracket syntax with predicates in [@attr='123'] or [@attr], which returns true if its EBV is true. But if it evaluates to a number, it will return the nth item from the sequence.

For the discussion, let's replace your expression elem1/elem2[@attr='123'] with EXPR for brevity, and the rest like:

X + EXPR * Y

Where the idea is to get as close as possible to the Iverson syntax for EXPR.

XPath 2.0

Your expression requires less parentheses:

X + if(EXPR) then 1 else 0 * Y

This can also be written as the following, assuming false-value of EXPR is an empty sequence:

X + (EXPR, 1, 0)[2] * Y

Is there a more simple syntax than "boolean(...)"?

You suggested the boolean(EXPR) function, but as you mentioned in the comments, this will not work, you need to convert it to a number, for instance with:

X + number(boolean(EXPR)) * Y

I think the shortest version in XPath 2.0 is the empty-sequence dismissal approach, but it may not always work, it requires the first item to return the empty sequence.

If you have a validating processor that sets the element as boolean, you can use:

X + number(EXPR) * Y

Or if typed as a number with valid values 0 and 1, just:

EXPR

XPath 3.0

Let's see if with the new XPath 3.0 syntax we can get even simpler:

let $Iv := function($i) { number(boolean($i)) }
return X + $Iv(EXPR) * Y

With XQuery and XSLT, but also XPath, you can declare this variable globally, which changes the expression into:

X + $Yv(EXPR) * Y

But you'll still have to deal with the parentheses, but keep reading...

XPath 3.1

In 3.1, the arrow operator has been introduced, which allows your original example to be written as:

X + EXPR=>boolean()=>number() * Y

Given that we now have a global variable with a function item, we can do:

X + EXPR=>$Iv() * Y

Other approach

Since setting a global variable to an anonymous function is nothing more than creating a function, we can also declare a function in XQuery or XSLT. Something like:

X + EXPR=>i:v() * Y

Upvotes: 5

Related Questions