XPath query for XML node with colon in node name - xpath

What XPath query will select the <media:thumbnail /> node in the following XML?
<item>
<title>Sublime Federer crushes Wawrinka</title>
<description>Defending champion Roger Federer cruises past Stanislas Wawrinka 6-1 6-3 6-3 to take his place in the Australian Open semi-finals.</description>
<link>http://news.bbc.co.uk/go/rss/-/sport2/hi/tennis/9372592.stm</link>
<guid isPermaLink="false">http://news.bbc.co.uk/sport1/hi/tennis/9372592.stm</guid>
<pubDate>Tue, 25 Jan 2011 04:21:23 GMT</pubDate>
<category>Tennis</category>
<media:thumbnail width="66" height="49" url="http://news.bbcimg.co.uk/media/images/50933000/jpg/_50933894_011104979-1.jpg"/>
</item>
The XML came from this RSS feed.

You need to learn about namespaces and how to define/register a namespace in your XPath engine so that you can then use the associated prefix for names in that registered namespace. There are plenty of questions in the xpath tag asking how to use names that are in a namespace -- with good answers. Search for them.
A very rough answer (ignoring namespaces at all) is:
//*[name()='media:thumbnail']

What worked for me is:
/item/*[local-name()='thumbnail']

If you're looping an XmlNodeList array
just use *[local-name()='thumbnail']

Related

XPATH How to Select two specific chidren from a same parent

Good night, friends!
Lets suppose we have a xml with 30 items like that and I want to get just the name and url from an item where name contains the word: Richard.
<channel>
<item>
<name>Brian</name>
<lastname>Connor</lastname>
<age>40</age>
<enclosure url="http://www.brian.com"/>
</item>
<item>
<name>Richard</name>
<lastname>Wendell</lastname>
<age>38</age>
<enclosure url="http://www.richard.com"/>
</item>
</channel>
How can I do that using XPath?
I tried:
"//channel/item[name[contains(text(),'Richard')]]" but it returns just the name and I don't know how to select the url information together.
Please excuse my english!
Your approach does not work because you are selecting a sub tree (in this case an item) of the XML tree which contains more information than you want. If you want just a subset of the attributes in ONE xpath expression you have to select them separately and then concatenate them adequately, e.g.
concat('name=', //channel/item[contains(name, 'Richard')]/name, ' url=', //channel/item[contains(name, 'Richard')]/enclosure/#url)
The example will allow you to alter the additional formatting easily.
By the way: your XML input was malformatted. I corrected this.

Xpath - how to differentiate nodes without attributes?

I want to extract a value from xml via xpath and I'm struggling a bit. This is the example of xml I have to work with
<data>
<menu>
<date>2017-10-30</date>
<type>S</type>
<name>onion soup</name>
</menu>
<menu>
<date>2017-10-30</date>
<type>L</type>
<name>ham sandwich</name>
</menu>
<menu>
<date>2017-10-31</date>
<type>S</type>
<name>pumpkin soup</name>
</menu>
<menu>
<date>2017-10-31</date>
<type>L</type>
<name>cheese sandwich</name>
</menu>
<menu>
<date>2017-11-1</date>
<type>S</type>
<name>sweet potato soup</name>
</menu>
<menu>
<date>2017-11-1</date>
<type>L</type>
<name>chicken sandwich</name>
</menu>
</data>
The dates and meal names are dynamically changing.
Now I have 2 columns, for Today's soup and Tomorrow's. I know how to link to xml via xpath for today's soup:
/data/menu/name[../type/text() = "S"] or /data/menu[type[text()='S']]/name
But I struggle with tomorrow's as my xml feed doesn't have any attributes to differentiate, types are the same for both dates and date is constantly changing.
Thanks for any help.
Edit:
Thank you for anwering.
I think I described my problem wrong.
I should probably point out that I'm using Xpath build-in feature in one of the local software.
You're right, these lines
/data/menu[type='S' and date='2017-10-31']]/name
are for all the soups, I just wrongly described it by how it behaves on my end, where it gives me just the value of the first one.
/data/menu[type='S' and date='2017-11-01']]/name
will give me Tommorow's soup, but if I want to use output for this value in static column "Tommorow's soup" next to which I want my xpath output it will only be true for one day. What I need is for it to be true also for next days.
I need a line that will give me "tommorow's soup" which is suppose to be Pumpkin soup today, tommorow when the xml updates it would be Sweet Potato soup and day after that it will be some new soup which is going to be updated later with the whole xml.
If I use
/data/menu[type='S' and date='2017-10-30']]/name
it will not show anything tommorow since there won't be a 2017-10-30 because the xml will update and will start with 2017-10-31.
I hope it's clearer now what I'm asking. I know it's still confusing it's kinda hard for me to describe it in English especially since I'm beginner when it comes to Xpath.
How to differentiate elements without attributes? Use other elements...
But first to clear up a wrong assumption:
Now I have 2 columns, for Today's soup and Tomorrow's. I know how to
link to xml via xpath for today's soup:
/data/menu/name[../type/text() = "S"] or
/data/menu[type[text()='S']]/name
Actually, the XPaths that you say will give you today's soups will actually give you all soups regardless of date.
XPath 1.0
XPath 1.0 has no date functions1, so you'll have to pass the current date and tomorrow's date into your XPAth, and you're on your own to test the date element's value as a string:
If today is 2017-10-31, then this XPath will give you the names of today's soups,
/data/menu[type='S' and date='2017-10-31']]/name
and this XPath will give you the names of tomorrow's soups:
/data/menu[type='S' and date='2017-11-1']]/name
1
XPath 2.0 and 3.0's dynamic context includes a current-dateTime() function, but its format is implementation-dependent, which limits its usefulness. You might be able to use date calculations to determine tomorrow's date, but unless you want to be dependent upon an implementation-defined format for current-dateTime(), you'll have to pass today into your XPath at least.

Xpath for an element , all ancestors of which have the same name up to a point

I have an XML that looks like the following:
xml tree
I need those tag elements that have only son elements as their ancestors.The only non-son ancestor allowed is the root element parent.After parent no ancestor of tag can be anything other than son . This xpath therefore would return <tag id="t1" /> and <tag id="t2" />
//son//tag would be one solution. Another would be //tag[ancestor::son] You could use /descendent:: in place of //; there are differences in the order in which results are reported. There are other variants; which one is best depends on the exact context in which you're doing this.
I should have posted this earlier or may be it does not matter.Here is the nasty looking xpath I wrote to solve this:
/parent/(descendant::tag except(descendant::element() except descendant::son)/descendant::tag)
Hope someone would suggest a better looking alternative.

Xpath - How to select subnode where sibling-node contains certain text

I want to use XPath to select the sub tree containing the <name>-tag with "ABC" and not the other one from the following xml. Is this possible? And as a minor question, which keywords would I use to find something like that over Google (e.g. for selecting the sub tree by an attribute I would have the terminology for)?
<root>
<operation>
<name>ABC</name>
<description>Description 1</description>
</operation>
<operation>
<name>DEF</name>
<description>Description 2</description>
</operation>
</root>
Use:
/*/operation[name='ABC']
For your second question: I strongly recommend not to rely on online sources (there are some that aren't so good) but to read a good book on XPath.
See some resources listed here:
https://stackoverflow.com/questions/339930/any-good-xslt-tutorial-book-blog-site-online/341589#341589
For your first question, I think a more accurate way to do it would be://operation[./name[text()='ABC']].And according to this , we can also make it://operation[./name[text()[.='ABC']]]

Xpath Axes - how to select child node attribute

I have the following XML:
<ArrayOfStationStatus xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" autopagerMatchedRules="1">
<StationStatus ID="20" StatusDetails="To the platform due to planned maintenance work.">
<Station ID="20" Name="Bermondsey"/>
<Status ID="NS" CssClass="Closed" Description="No Step Free Access" IsActive="true">
<StatusType ID="2" Description="Station"/>
</Status>
</StationStatus>
</ArrayOfStationStatus>
And would like to select StationStatus nodes that contain a particular phrase in the Name attribute. It's important that I select SationStatus nodes.
This is the xpath I have come up with but it's not correct:
/ArrayOfStationStatus/StationStatus[contains(lower-case(child::Station/#Name),lower-case('phrase'))]
EDIT::::::::
I just solved it! This is the code I needed:
/ArrayOfStationStatus/StationStatus[child::Station[contains(lower-case(attribute::Name),lower-case("Ac"))]]
Well I managed to solve it people! Here is the solution, in this case I'm looking for the phrase 'Ac' as you can see
/ArrayOfStationStatus/StationStatus[child::Station[contains(lower-case(attribute::Name),lower-case("Ac"))]]
Also remember
lower-case(
is only available in xpath 2.0 (Dimitre Novatchev)

Resources