xpath for price with currency - xpath

<category>
<Movi Name="Test">
<Price>$3.95</Price>
</Movi>
<Movi Name="test d">
<Price>$13.95</Price>
</Movi>
</category>
can anyone help on this XML to find movie greater than $11 with XPath

Given all prices are in the same currency and format, this bit of XPath does the job:
/category/Movi[number(substring(./Price/text(), 2)) > 11]

Just for the sake of completeness, another option is:
//Price[number(translate(text(), '$','')) > 11]

Related

Get the position of an element with specific attribute value

I'm trying to get with xPath the position only of the first element which has the attribute value true.
<?xml version="1.0" encoding="UTF-8"?>
<elements>
<element attribute="false"/>
<element attribute="true"/>
<element attribute="true"/>
</elements>
What I have so fare is:
head(/elements/element[#attribute='true']/position())
Result:
1
But it should be:
2
What am I doing wrong?
position() returns the position of the element in the nodelist created by the predicate, i.e. with the false excluded. Instead of position, you can e.g. count the number of preceding elemements.
For example, this works even in XPath 1.0:
1+count(/elements/element[#attribute="true"][1]/preceding-sibling::element)
I think it's (with XPath 3):
head(index-of(/elements/element/#attribute, 'true'))
saxon-lint --xpath 'count(//element[#attribute="true"]/position())' file.xml
From Michael answer:
saxon-lint --xpath 'head(index-of(/elements/element/#attribute, "true"))' file.xml
Output
2

How to compare element position in xpath

I am trying to compare customer account values to display only different values and ignore duplicate in XPath:
XML code:
<info>
<Customer CustAccount="1"/>
<Customer CustAccount="2"/>
<Customer CustAccount="2"/>
<Customer CustAccount="3"/>
</info>
The result should compare customer 1/2/3 and display:
customer 1
customer 2
customer 3
You can achieve this with the XPath-2.0 expression
for $c in distinct-values(/info/Customer/#CustAccount) return concat('customer ',$c,'
')
Output is:
customer 1
customer 2
customer 3
If you do not like the newlines, remove the
from the expression.
There is no pure XPath-1.0 expression achieving this; you could only do this with XSLT-1.0 if XPath-2.0 is unavailable.
Here is the pure xpath 1.0 solution.
Sample xml:
<root >
<info>
<Customer CustAccount="1"/>
<Customer CustAccount="2"/>
<Customer CustAccount="2"/>
<Customer CustAccount="3"/>
</info>
</root>
xpath 1.0:
/root/info/Customer[not(./#CustAccount=preceding::Customer/#CustAccount)]
Evidence:

Is there a way to get the nodes whose child value is not equal to another child axis?

I have this XML and I'm trying to get all of the /root/ecommerce/cart/product whose branduid child is not present in /root/ecommerce/promo/promobrands/promobrand/branduid values.
<root>
<ecommerce>
<cart>
<product>
<branduid>value1</branduid>
</product>
<product>
<branduid>value2</branduid>
</product>
<product>
<branduid>value3</branduid>
</product>
<product>
<branduid>value4</branduid>
</product>
</cart>
<promo>
<promobrands>
<promobrand>
<branduid>value1</branduid>
</promobrand>
<promobrand>
<branduid>value3</branduid>
</promobrand>
</promobrands>
</promo>
</ecommerce>
</root>
So I only have to get the /root/ecommerce/product nodes whose branduid values are value2 and value4.
Is there a way in XPath to get this result?
Try below XPath expression and let me know the result
//cart/product[branduid[not(text()=//promobrand/branduid/text())]]
If you are using xpath 2.0 , below expression is a straightforward way to achieve:
//branduid except //promobrand/branduid
otherwise Andersson's answer is good.

Double node on Xpath for different values

How to write a Xpath for two attributes? e.g. i need to get a value of discount > 20% and also the same discount is greater than amount 200(without any link to base value)
You can combine constraints in predicates. E.g.:
from lxml import etree
doc = etree.XML("""<xml>
<items>
<item discount_perc="25" discount_value="250">Something</item>
</items>
</xml>
""")
doc.xpath('items/item[#discount_perc > 20 and #discount_value > 200]')
Will try to answer by a simple example. Imagine you have the following xml:
<?xml version="1.0"?>
<data>
<node value="10" weight="1">foo</node>
<node value="10" weight="2">bar</node>
</data>
Then use this query to select the first <node>'s text:
//node[#value="10" and #weight="1"]/text()
and this for the second:
//node[#value="10" and #weight="2"]/text()
Hope this helps.

Selecting Nodes under two different conditions in XPath

I'm working on a Query in XPath and somehow I just can't get it to work.
I've got more cars in my "garage" of course, but to solve the problem, the two Nodes will do it:
<garage>
<car>
<data>
<brand name="Mazda" model="MX5"></brand>
<country>Japan</country>
<ctype>Cabriolet</ctype>
<motor fueltype="Super">
<ps>146</ps>
<kw>107</kw>
<umin>5000</umin>
</motor>
<price>22000</price>
</data>
</car>
<car>
<data>
<brand name="Audi" model="RS6"></brand>
<country>Germany</country>
<ctype>Limousine</ctype>
<motor fueltype="Super">
<ps>580</ps>
<kw>426</kw>
<umin>6250</umin>
</motor>
<price>108000</price>
</data>
</car>
</garage>
I want to count all cars, that are from japan AND got at least 100 ps (ps means horsepower in german). In the example above the result should be 1, because only the mx5 matches both conditions. I tried "and", I tried "intersect" and now I'm out. Could someone help me out, PLEASE!!!!!!
Here you go:
/garage/car[data/country = 'Japan' and data/motor/ps >= 100]
or:
/garage/car[data/country = 'Japan'][data/motor/ps >= 100]
or:
/garage/car[data[country = 'Japan'][motor/ps >= 100]]
The above are all equivalent. To get the count, wrap any of the above with count(...).

Resources