Easy way to transform XPath with contains to equals check? - xpath

Is there an easy way to transform an XPath query (as string), like:
my/x/path[contains(sub/path, 'text')]
to an XPath query which uses equals instead of contains? Such that I can easily use the same query, one time with contains and another time with equals? Unfortunately there is no "equals" function in XPath...

You might differentiate between the two options via a flag:
my/x/path[ ($wantContains and contains(sub/path, 'text'))
or
(not($wantContains) and sub/path = 'text')
]

Related

How to use wildcard attribute name and contains()?

In my problem I search for elements that have an example structure like:
<ngc-product-card ng-reflect-signup-type="comprehensive">
Since the elements may have the comprehensive value stored in another attribute, say:
<new-ngc-product-card data-label="comprehensive signup">
hence I would like to use a wildcard-attribute-name search and also apply the contains() function like:
//*[contains(#*,"comprehensive")]
which doesn't work
What does work is
//*[#*="comprehensive"]
Is there any way to use both '#*' and 'contains()' ?
This should do.
//*[#*[contains(., "comprehensive")]]

Xpath multiply formatted output

Have a many entries in an xml file and have xpath with condition:
/XMLReport/Report/PreflightResult/PreflightResultEntry[
#type = 'Check' and #level = 'warning']/PreflightResultEntryMessage/Message/text()
The output is:
onetwothreefour... and more
I need separation
'---' one---two---three---four
or
[enter]
one
two
three
four
Its possible ?
Why you bound XPath expression inside single quote ':
Use this:
string-join(/XMLReport/Report/PreflightResult/PreflightResultEntry[#type = 'Check' and #level = 'warning']/PreflightResultEntryMessage/Message/text(), '---')
Your XPath expression is actually returning a set of text nodes. The way these are displayed depends on the calling application (which you haven't told us anything about). I think your options are (a) change the way the calling application displays the result, or (b) if you're using XPath 2.0+, use the string-join() function to return the result as a string, formatted any way you like within the XPath expression itself.

assistance needed constructing JSONata query

I am trying to construct a JSONata query using the try.jsonata.org Invoice data.
The query I am trying to pose is select distinct OrderID where Order.Product.Price is < 50?
I have not been able to figure out how to do this using the predicate in square brackets notation ... my attempts have been thwarted when I try to get past the $.Account.Order.Product array.
Using $map and $reduce I was able to come up with this rather complex solution ... which still doesn't correctly handle duplicate OrderIDs. (I see that the issue of duplicate removal has been requested here)
Q: What is the proper way to express this query in JSONata?
I think this does what you need:
Account.Order[Product.Price.($ < 50)].OrderID
The expression in the predicate, which gets tested for each Order, will generate an array of Booleans (one for each Product.Price). The resulting predicate will evaluate to true if any of the Booleans within that array are true, due to the semantics of the $boolean function which is implicitly applied.
Overall, the expression will return the OrderID for every Order which has at least one Product whose Price is less than 50

Prefix the result of a XPATH query

I use libxmljs to parse some html.
I have a xpath query which has an "or" conjunction to retrieve basically the information of two queries
Example
doc.find("//div[contains(#class,'important') or contains(#class,'overdue')]")
this returns all the divs with either important or overdue...
Can I prefix or see within my result set which comes from which condition?
The result could be an array with an index for the match 0 for the first condition and 1 for the 2... Is this possible...
Or how can I find out which result comes from which query condition...
Thanks for any help...
P.S.: this is a simplified exampled of a sequence of elements which either have an important or an overdue item ... both, one or none of them... So I cannot go by looking for every second entry ... etc
This is the result I want to get...
message:{},
message:{
.....
important: "some immportant text",
overdue: "overdue date,
.....
}
There is no way to know which clause of an or XPath query caused a particular result to be included. It's simply not information that's kept around.
You'll either need to do entirely separate queries for important and overdue, or do one large query to get the entire result set (as you are now) and then further test each result's class to find out which one it is.

Query multiple elements without specifying the element name

This may be a silly question, but is it possible to make a query using XPath without specifying the element name?
Normally I would write something like
//ElementName[#id = "some_id"]
But the thing is I have many (about 40) different element types with an id attribute and I want to be able to return any of them if the id fits. But I don't want to make this call for each type individually. Is it possible to search all of them at once, regardless of the name?
I am using this in an XQuery script, if that offers any help.
use * instead of name //*[#id = "some_id"]
It might be more efficient to look directly at the #id elements - //* will work, but will initially return every node in the document and then filter!
That may not matter in a small document, of course. but here's an alternative:
//#id[.="some_id"]/..

Resources