How to sort file path names in hierarchy basis? - sorting

I want to sort out file names in hierarchy basis.
Let say I have below list of folders:
D:Movies\Hollywood\Comedy\adultcomedy
D:Movies\Hollywood\Comedy\horrorcomedy
D:Movies\Hollywood\Romantic\ adult
D:Movies\Bollywood\Action\comedy
D:Movies\Bollywood
D:Movies\Hollywood\Comedy
D:Movies\Hollywood
D:Movies
D:Movies\Hollywood\Romantic
I want to sort them in single line, which means the last children should be sorted first, and grand grand parent should be sorted as last Child
(I.e):
Movies — Grand parent
Hollywood — child of Movies
Bollywood — child of movies / Sibiling of Hollywood
Comedy — child of hollywood / grand child of Movies
adultcomedy— child of Comedy / descendant for Movies
horrorcomedy — child of Comedy /sibiling of adultcomedy
Romantic — child of Hollywood / Sibiling of Comedy and same for others
Here by I wanted to sort this as descendant from grand parent.
(i.e) —> 4 th level is extreme grand child in this structure, which means it should sort:
As first element adultcomedy
then it’s sibiling horrorcomedy
then 4th Level of grand children adult from Romantic
then comedy from Action
then Comedy which is child of Hollywood and parent of adultcomedy,horrorcomedy and
then Romantic
then Hollywood
then Bollywood
finally Movies.
D:Movies\Hollywood\Comedy\adultcomedy D:Movies\Hollywood\Comedy\horrorcomedy D:Movies\Hollywood\Romantic\ adult
D:Movies\Bollywood\Action\comedy D:Movies\Hollywood\Comedy D:Movies\Hollywood\Romantic D:Movies\Hollywood D:Movies\Bollywood
D:Movies
Here I can’t use array,. Only I can use tree strucutre to solve this problem.,
What I have tried.,
tried to count length but it’s failed due to dynamic path change
checked whether another path has substring of another path
But none of the algorithms are working.
Sample code to understand the structure:
<forall _="ChildrenWithKey" name="fDir" in="vtList" param="ElementDir" >
<!-- here vtList has element paths as children & all the path has a Key:ElementDir name- alias name, so that we can use this tree anywhere -->
<!-- lets consider the list of paths above mentioned all has a Key:ElementDir -->

Related

What is the difference between "element" and "//element" in XPath?

I am reading this XPath examples: https://msdn.microsoft.com/en-us/library/ms256086(v=vs.110).aspx and I want to know the difference between these 2 expressions:
author
All <author> elements within the current context.
//author
All <author> elements in the document.
What is the difference between these two cases? If the "current context" is the root node, would that make the two equivalent?
For this simple XML file:
<root>
<author>
<first-name></first-name>
</author>
</root>
I tried it on this site https://www.freeformatter.com/xpath-tester.html
Why does author not returning anything as I expected it should (but //author works)?
The description you cite for the relative XPath expression, author,
All <author> elements within the current context.
is wrong1. It should instead say,
All <author> child elements of the current context node.
//author would indeed select all <author> elements in the document because // selects along the descendant-or-self axis.
The reason author doesn't select anything for your XML document is that with the context node set to the document root, you'd have to include root/author to select the <author> children of <root> or just root to select the <root> element itself.
1 As of today, 2018-06-24, but I've submitted feedback that it should be corrected, so hopefully it will fixed be soon.
"element" selects all immediate children named "element" of the current node and is identical to "./element".
"//element" selects all "element" nodes at any depth, starting from the root (ignoring your current node).
And to complete the list:
".//element" would select "element" children below the current node, at any depth.
"/element" would search at the root level only (in you example, you would need "/root" to get anything).
And as for "author" not finding anything: you first need to be at the level of your root node. "/root/author" would get the node you wanted, or first select "/root" and from there you can select "author".

What is the difference between xpath //a and .//a in Selenium Webdriver [duplicate]

While finding the relative XPath via Firebug : it creates like
.//*[#id='Passwd']--------- what if we dont use dot at the start what it signifies?
Just add //* in the Xpath --
it highlights --- various page elements ---------- what does it signify?
Below are XPaths for Gmail password fields. What is significance of * ?
.//*[#id='Passwd']
//child::input[#type='password']
There are several distinct, key XPath concepts in play here...
Absolute vs relative XPaths (/ vs .)
/ introduces an absolute location path, starting at the root of the document.
. introduces a relative location path, starting at the context node.
Named element vs any element (ename vs *)
/ename selects an ename root element
./ename selects all ename child elements of the context node.
/* selects the root element, regardless of name.
./* or * selects all child elements of the context node, regardless of name.
descendant-or-self axis (//*)
//ename selects all ename elements in a document.
.//ename selects all ename elements at or beneath the context node.
//* selects all elements in a document, regardless of name.
.//* selects all elements, regardless of name, at or beneath the context node.
With these concepts in mind, here are answers to your specific questions...
.//*[#id='Passwd'] means to select all elements at or beneath the
context node that have an id attribute value equal to
'Passwd'.
//child::input[#type='password'] can be simplified to
//input[#type='password'] and means to select all input elements
in the document that have an type attribute value equal to 'password'.
These expressions all select different nodesets:
.//*[#id='Passwd']
The '.' at the beginning means, that the current processing starts at the current node. The '*' selects all element nodes descending from this current node with the #id-attribute-value equal to 'Passwd'.
What if we don't use dot at the start what it signifies?
Then you'd select all element nodes with an #id-attribute-value equal to 'Passwd' in the whole document.
Just add //* in the XPath -- it highlights --- various page elements
This would select all element nodes in the whole document.
Below mentioned : XPatht's for Gmail Password field are true what is significance of * ?
.//*[#id='Passwd']
This would select all element nodes descending from the current node which #id-attribute-value is equal to 'Passwd'.
//child::input[#type='password']
This would select all child-element nodes named input which #type-attribute-values are equal to 'password'. The child:: axis prefix may be omitted, because it is the default behaviour.
The syntax of choosing the appropriate expression is explained here at w3school.com.
And the Axes(current point in processing) are explained here at another w3school.com page.
The dot in XPath is called a "context item expression". If you put a dot at the beginning of the expression, it would make it context-specific. In other words, it would search the element with id="Passwd" in the context of the node on which you are calling the "find element by XPath" method.
The * in the .//*[#id='Passwd'] helps to match any element with id='Passwd'.
For the first question: It's all about the context. You can see Syntax to know what '.', '..' etc means. Also, I bet you won't find any explanation better than This Link.
Simplified answer for second question: You would generally find nodes using the html tags like td, a, li, div etc. But '*' means, find any tag that match your given property. It's mostly used when you are sure about a given property but not about that tag in which the element might come with, like suppose I want a list of all elements with ID 'xyz' be it in any tag.
Hope it helps :)

XPATH - cannot select grandparent node

I am trying to parse a live betting XML feed and need to grab each bet from within the code. In plain English I need to use the tag 'EventSelections' for my base query and 'loop' through these tags on the XML so I grab all that data and it creates and entity for each one which I can use on a CMS.
My problem is I want to go up two places in the tree to a grandparent node to gather that info. Each EventID refers to the unique name of a game and some games have more bets than others. It's important that I grab each bet AND the EventID associated with it, problem is, this ID is the grandparent each time. Example:
<Sportsbet Time="2013-08-03T08:38:01.6859354+09:30">
<Competition CompetitionID="18" CompetitionName="Baseball">
<Round RoundID="2549" RoundName="Major League Baseball">
<Event EventID="849849" EventName="Los Angeles Dodgers (H Ryu) At Chicago Cubs (T Wood)" Venue="" EventDate="2013-08-03T05:35:00" Group="MTCH">
<Market Type="Match Betting - BIR" EachWayPlaces="0">
<EventSelections BetSelectionID="75989549" EventSelectionName="Los Angeles Dodgers">
<Bet Odds="1.00" Line=""/>
</EventSelections>
<EventSelections BetSelectionID="75989551" EventSelectionName="Chicago Cubs">
<Bet Odds="17.00" Line=""/>
</EventSelections>
Does anyone know how I can grab the granparent tags as well?
Currently I am using:
//EventSelections (this is the context)
.//#BetSelectionID
.//#EventSelectionName
I have tried dozens of different ways to do this including the ../.. operator which won't work either. I'd be eternally grateful for any help on this. Thanks.
I think you just haven't gone far enough up the tree.
../* is a two-step location bath with abbreviations, expanded to parent::node()/child::* ... so in effect you are going up the tree with the first step, but back down the tree for the second step.
Therefore, ../* gives you your siblings (parent's children), ../../* gives you your aunts and uncles (grandparent's children), and ../../../* gives you your grandparent and its siblings (great-grandparent's children).
For attributes, ../#* is an abbreviation for parent::node()/attribute::* and attributes are attached to elements, they are not considered children. So you are going sideways, not down the tree in the second step.
Therefore, unlike above, ../#* gives you your parent's attributes, while ../../#* gives you your grandparent's attributes.
But using // in your situation is really inappropriate. // is an abbreviation for /descendent-or-self::node()/ which walks all the way down a tree to the leaves of the tree. It should be used only in rare occasions (and I cringe when I see it abused on SO questions).
So ..//..//..//#RoundID may work for you, but it is in effect addressing attributes all over the tree and not just an attribute of your great-grandparent, which is why it is finding the attribute of your grandparent. ../../#RoundID should be all you need to get the attribute of your grandparent.
If you torture a stylesheet long enough, it will eventually work for you, but it really is more robust and likely faster executing to address things properly.
You could go with ancestor::Event/#EventID, which does exactly you asked for: matches an ancestor element named Event and returns it's EventID attribute.

XPath test to identify node type

I don't understand why this test
count(.|../#*)=count(../#*)
( from Dave Pawson's Home page )
identify an attribute node :(
could someone give me a detailled explanation ?
A few things to understand:
. refers to the current node (aka "context node")
an attribute node has a parent (the element it belongs to)
an XPath union operation (with |) never duplicates nodes, i.e. (.|.) results in one node, not two
there is the self:: axis you could use in theory (e.g. self::* works to find out if a node is an element), but self::#* does not work, so we must use something different
Knowing that, you can say:
../#* fetches all attributes of the current node's parent (all "sibling attributes", if you will)
(.|../#*) unions the current node with them – if the current node is an attribute, the overall count does not change (as per #3 above)
therefore, if count(.|../#*) equals count(../#*), the current node must be an attribute node.
Just for completeness, in XSLT 2.0 you can do
<xsl:if test="self::attribute()">...</xsl:if>
Here is how this works
count( # Count the nodes in this set
.|../#*) # include self and all attributes of the parent
# this counts all of the distinct nodes returned by the expression
# if the current node is an attribute, then it returns the count of all the
# attributes on the parent element because it does not count the current
# node twice. If it is another type of node it will return 1 because only
# elements have attribute children
=count( # count all the nodes in this set
../#*) # include all attribute nodes of the parent. If the current node is not an
# attribute node this returns 0 because the parent can't have attribute
# children

Modify XPath to return second of two values

I have an XPath that returns two items. I want to modify it so that it returns only the second, or the last if there are more than 2.
//a[#rel='next']
I tried
//a[#rel='next'][2]
but that doesn't return anything at all. How can I rewrite the xpath so I get only the 2nd link?
Found the answer in
XPATH : finding an attribute node (and only one)
In my case the right XPath would be
(//a[#rel='next'])[last()]
EDIT (by Tomalak) - Explanation:
This selects all a[#rel='next'] nodes, and takes the last of the entire set:
(//a[#rel='next'])[last()]
This selects all a[#rel='next'] nodes that are the respective last a[#rel='next'] of the parent context each of them is in:
//a[#rel='next'][last()] equivalent: //a[#rel='next' and position()=last()]
This selects all a[#rel='next'] nodes that are the second a[#rel='next'] of the parent context each of them is in (in your case, each parent context had only one a[#rel='next'], that's why you did not get anything back):
//a[#rel='next'][2] equivalent: //a[#rel='next' and position()=2]
For the sake of completeness: This selects all a nodes that are the last of the parent context each of them is in, and of them only those that have #rel='next' (XPath predicates are applied from left to right!):
//a[last()][#rel='next'] NOT equiv!: //a[position()=last() and #rel='next']

Resources