Xpath queries based on given node - xpath

I have a this xml:
<?xml version="1.0"?>
<catalog>
<car>
<id>0</id>
<color>green</color>
<color>red</color>
<color>yellow</color>
<vip>
<user>Trump</user>
<user>Obama</user>
<user>Merkel</user>
</vip>
</car>
<car>
<id>1</id>
<color>green</color>
<color>red</color>
<color>yellow</color>
<vip>
<user>Putinski</user>
<user>Orlovski</user>
<user>Idiotski</user>
</vip>
</car>
<car>
<id>2</id>
<color>green</color>
<color>red</color>
<color>yellow</color>
<vip>
<user>Clooney</user>
<user>Lopez</user>
<user>Ford</user>
</vip>
</car>
</catalog>
And I am fighting with some simple things:
a) count the "color" nodes from car id 0
b) retrieve Obama's car id
For a) I know how to identify car id 0
/catalog/car/id=0
gives me a TRUE - so this is the proof I am on the right track. But now how can I continue counting the "color" nodes based on car id 0? The solution postet here does not work, as well as the following-sibling results in an javax.xml.transformerException. Does anybody know how to solve this?

To count the color nodes in car with id = 0 you can use
count(/catalog/car[id="0"]/color)
Returns 3
To get Obama's car id:
/catalog/car[.//user="Obama"]/id/text()
Returns 0

Related

Select Xpath element value based on value of another element

I am trying to capture a value using XPath based on value of a different field.
Example XML:
<?xml version="1.0" encoding="UTF-8" ?>
<employees>
<employee>
<id>1</id>
<firstName>Tom</firstName>
<lastName>Cruise</lastName>
<photo>https://jsonformatter.org/img/tom-cruise.jpg</photo>
</employee>
<employee>
<id>2</id>
<firstName>Maria</firstName>
<lastName>Sharapova</lastName>
<photo>https://jsonformatter.org/img/Maria-Sharapova.jpg</photo>
</employee>
<employee>
<id>3</id>
<firstName>Robert</firstName>
<lastName>Downey Jr.</lastName>
<photo>https://jsonformatter.org/img/Robert-Downey-Jr.jpg</photo>
</employee>
</employees>
I am trying to get Xpath expression for value in the firstName field, when id value is 3.
You can locate parent node based on the known child node and then find the desired child node of that parent, as following:
//employee[./id='3']/firstName
the expression above will give the desired firstName node itself.
To retrieve it's text value this can be used:
//employee[./id='3']/firstName/text()

Find information about newest element in XQuery

I have a xml file like this:
<carSchema xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="carSchema.xsd">
<car>
<License>23</License>
<year>2010</year>
<model>a</model>
<manufacturer>hyundai</manufacturer>
</car>
<car>
<License>24</License>
<year>2002</year>
<model>b</model>
<manufacturer>hyundai</manufacturer>
</car>
<car>
<License>25</License>
<year>2005</year>
<model>c</model>
<manufacturer>hyundai</manufacturer>
</car>
<car>
<License>26</License>
<year>2004</year>
<model>d</model>
</car>
<car>
<License>27</License>
<year>2016</year>
<model>f</model>
<manufacturer>hyundai</manufacturer>
</car>
I want to find information about newest car in Xquery. I wrote this Query that return year of newest car.
xquery version "1.0";
max(
for $x in doc("car.xml")/carSchema/car
order by $x/year descending
return $x/year)
How I return all information about that car(License, model, manufacturer)?
You can use
(for $car in doc("car.xml")/carSchema/car
order by $car/year descending
return $car)[1]/*
to find all child elements of the element with the latest year or
(for $car in doc("car.xml")/carSchema/car
order by $car/year descending
return $car)[1]
to find the element itself with the latest year.

Linq to XML - get elements that have certain child element

Using LINQ to XML, how do I get a collection of all elements that have a named child element.
for example;
<root>
<Garage>
<Car id="001">
<Price PaymentType="Cash">$100</Price>
</Car>
<Car id="002">
<Price PaymentType="Cash">$200</Price>
</Car>
<Car id="003">
</Car>
</Garage>
</root>
this will return 2 Car elements (#1 and #2) as they have the Price element. It won't return Car #3, as it doesn't have a price element.
thanks as always
Assuming you have an XDocument object named doc with your example xml loaded into it. You could try something like this.
IEnumerable<XElement> elements = doc.Descendants("Garage").Elements().Where(e => e.Elements().Any());

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