Implementing condition in XPath
Specify the date in the xpath expression,
i.e.
$nodes = $xml->xpath('//xml/events[@date="14/12/2011"]');
would select only the last events-node in the example
XPath with multiple conditions
Try://category[@name='Sport' and ./author/text()='James Small']
Using an OR condition in Xpath to identify the same element
If the element has two xpath, then you can write two xpaths like below
xpath1 | xpath2
Eg: //input[@name="username"] | //input[@id="wm_login-username"]
It will choose any one xpath
Multiple conditions (and operator) in XPath
It depends on the version of XPath.
You can't do this in a single XPath 1.0 expression because it would require a structure like
/bookstore/myBooks/book[/bookstore/books/book[
@title = _outer-predicate_/@title and
@author = _outer-predicate_/@author]]/@name
i.e. you'd need to capture the book being tested by the outer predicate so you can compare it to the inner one. Pure XPath 1.0 doesn't support this, you'd have to iterate over the content of myBooks
yourself (e.g. with an xsl:for-each
, as you've tagged your question "xslt").
In XPath 2.0 you can do it in one expression with an explicit quantifier
/bookstore/myBooks/book[not(some $book in /bookstore/books/book satisfies
($book/@author = @author and $book/@title = @title))]/@name
How to apply condition on child xpath from parent xpath
It would be something like:
//p[contains(text(), 'Pending')]/parent::td/following-sibling::*/descendant::*/button[contains(text(),'Waved off')]
Going forward please include the whole <table>
tag contents into your question, the chance of getting more accurate advice will be much higher
References:
- XPath Tutorial
- XPath Axes
- XPath Operators & Functions
Implement if condition for xpath that does not exist Karate
The karate.get()
API will gracefully return null if an XPath does not exist. So this works:
* def xml1 = <root><one>1</one></root>
* def temp = karate.get('$xml1/root/one')
* def result = temp ? 'yes' : 'no'
* match result == 'yes'
* def xml2 = <root><two>2</two></root>
* def temp = karate.get('$xml2/root/one')
* def result = temp ? 'yes' : 'no'
* match result == 'no'
Now just use the techniques in the docs on conditional logic and you should be able to do what you want. One more thing, there is nothing wrong with calling a second (re-usable) feature file, it can make things simpler in some cases.
Nested conditional if else statements in xpath
I. In XPath 2.0 one simply translates this to:
if(/*/propertyTypes/propertyType = 'RESIDENTIAL')
then
(if(/*/leasehold='Yes')
then 'Rent'
else 'Buy'
)
else
if(/*/leasehold='Yes')
then 'Leasehold'
else 'Freehold'
XSLT 2.0 - based verification:
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:template match="/">
<xsl:sequence select=
"if(/*/propertyTypes/propertyType = 'RESIDENTIAL')
then
(if(/*/leasehold='Yes')
then 'Rent'
else 'Buy'
)
else
if(/*/leasehold='Yes')
then 'Leasehold'
else 'Freehold'
"/>
</xsl:template>
</xsl:stylesheet>
When this transformation is applied on the provided XML document:
<property id="1011">
<leasehold>No</leasehold>
<freehold>Yes</freehold>
<propertyTypes>
<propertyType>RESIDENTIAL</propertyType>
</propertyTypes>
</property>
the XPath expression is evaluated and the result of this evaluation is copied to the output:
Buy
II. XPath 1.0 solution
In XPath 1.0 there isn't an if
operator.
A conditional statement can still be implemented with a single XPath 1.0 expression, but this is more tricky and the expression may not be too readable and understandable.
Here is a generic way (first proposed by Jeni Tennison) to produce $stringA
when a condition $cond
is true()
and otherwise produce $stringB
:
concat(substring($stringA, 1 div $cond), substring($stringB, 1 div not($cond)))
One of the main achivements of this formula is that it works for strings of any length and no lengths need to be specified.
Explanation:
Here we use the fact that by definition:
number(true()) = 1
and
number(false()) = 0
and that
1 div 0 = Infinity
So, if $cond
is false
, the first argument of concat()
above is:
substring($stringA, Infinity)
and this is the empty string, because $stringA
has a finite length.
On the other side, if $cond
is true()
then the first argument of concat()
above is:
sibstring($stringA, 1)
that is just $stringA
.
So, depending on the value of $cond
only one of the two arguments of concat()
above is a nonempty string (respectively $stringA
or $stringB
).
Applying this generic formula to the specific question, we can translate the first half of the big conditional expression into:
concat(
substring('rent',
1 div boolean(/*[leasehold='Yes'
and
propertyTypes/propertyType = 'RESIDENTIAL'
]
)
),
substring('buy',
1 div not(/*[leasehold='Yes'
and
propertyTypes/propertyType = 'RESIDENTIAL'
]
)
)
)
This should give you an idea how to translate the whole conditional expression into a single XPath 1.0 expression.
XSLT 1.0 - based verification:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:template match="/">
<xsl:copy-of select=
"concat(
substring('rent',
1 div boolean(/*[leasehold='Yes'
and
propertyTypes/propertyType = 'RESIDENTIAL'
]
)
),
substring('buy',
1 div not(/*[leasehold='Yes'
and
propertyTypes/propertyType = 'RESIDENTIAL'
]
)
)
)
"/>
</xsl:template>
</xsl:stylesheet>
When this transformation is applied on the provided XML document (above), the XPath expression is evaluated and the result of this evaluation is copied to the output:
buy
Do note:
If you decide to replace the specific strings with other strings that have different lengths than the original, you simply replace these strings in the above XPath 1.0 expression and you don't have to worry about specifying any lengths.
xpath multiple condition and return root
If you want to get the foo
elements, start the []
just after foo
:
//foo[bar/test/@val='hello' and bar/new/@val='world']
If you want the children of foo
, put the brackets there:
//foo/bar[test/@val='hello' and new/@val="world"]
Related Topics
MySQLi_Query() Expects Parameter 1 to Be MySQLi, Object Given
How to Remove an Array Element in a Foreach Loop
Simple Postgresql Statement - Column Name Does Not Exists
Prevent Direct Access to File Called by Ajax Function
PHP Fatal Error: Call to Undefined Function Mssql_Connect()
How to Find Out Where a Function Is Defined
Codeigniter Displays a Blank Page Instead of Error Messages
Date Difference in PHP on Days
PHP Array to Json Array Using Json_Encode();
Parsing Json Object in PHP Using Json_Decode
How to Get the Query Executed in Laravel 5? Db::Getquerylog() Returning Empty Array
MySQL: Select Random Entry, But Weight Towards Certain Entries
Check If a User/Guest Has Purchased Specific Products in Woocommerce
What's the Deal With a Leading Underscore in PHP Class Methods