How to select node which has a parent with some attributes - xpath

How to select node which has a parent with some attributes.
Eg: what is Xpath to select all expiration_time elements.
In the following XML, I'm getting error if states elements has attributes, otherwise no probs.
Thanks
<lifecycle>
<states elem="0">
<expiration_time at="rib" zing="chack">08</expiration_time>
</states>
<states elem="1">
<expiration_time at="but">4:52</expiration_time>
</states>
<states elem="2">
<expiration_time at="ute">05:40:15</expiration_time>
</states>
<states elem="3">
<expiration_time>00:00:00</expiration_time>
</states>
</lifecycle>

states/expiration_time[../#elem = "0"]?

Use:
/*/*/expiration_time
This selects all expiration_time elements that are grand-children of the top-element of the XML document.
/*/*[#*]/expiration_time
This selects any expiration_time element whose parent has at least one attribute and is a child of the top element of the XML document.
/*/*[not(#*)]/expiration_time
This selects any expiration_time element whose parent has no attributes and is a child of the top element of the XML document.
/*/*[#elem = '2']/expiration_time
This selects any expiration_time element whose parent has an elem attribute with string value '2' and that is (the parent) a child of the top element of the XML document.

This will give you all nodes having atleast one attribute
//*[count(./#*) > 0]

Related

XPath to get parents with multiple children but only one type of child

I need an XPath (1.0) to get all parent nodes with multiple children but only one type of child (e.g., either <div> or <li> but not <div> and <li>). Any help? Thank you!
<doc>
<tom>
<janet />
</tom>
<dick>
<janet />
<jane />
</dick>
<harry>
<jane />
</harry>
</doc>
So for the above we should get tom and harry but not dick
Using the example as a reference, the following XPath 1.0 expression:
/doc/*[count(./*) = count(./*[name(.) = name(../*[1])])]
Will return all children of doc where the total number of children of that element equals the number of children with the same name as the first child of that element. Or, more simply put, all children have the same name aka 'type'.
However, the above will return nodes that have 0 or 1 children, so to restrict it to only those where there are multiple child nodes, we can use:
/doc/*[count(./*) = count(./*[name(.) = name(../*[1])]) and count(./*) > 1]
If you want to further restrict it so that all children have to be a certain element, for example jane, you could use: /doc/*[count(./*) = count(./*[name(.) = name(../*[1])]) and count(./*) > 1 and ./*[1] = ./jane[1]]

Need a xpath : where parent having multiple child, but i required only parent value

In below code: parent "div" having three child "span", "script" and "span". but i required the value of Parent "div" which "N/A". "N/A" not comes under any attribute of div. Its just a value of parent "div".
<div class="ah-text-align-right ah-font-xsmall" style="">
<span id="_dcmanageinvestmentsportlet_WAR_ahdcmnginvportlet__FDROR_110hidden" style="display:none">
<script type="text/javascript">
<span class="ah-float-left">
N/A
</div>
For getting parent element you can use double dot .. after child element xpath.
For getting text of an element you can use xpath text() function, but depending on implementation of xpath in whatever environment and code you use, it might be unavailable. Note, that text of an element will return actual text node of this element as well as all text nodes of child elements.
For your case if you search a parent of a span with ah-float-left class, then xpath should be something like following:
//span[#class='ah-float-left']/..
For getting text of a parent, you'll need following:
//span[#class='ah-float-left']/../text()
Note: looking elements up by class name may return you a collection of elements which in turn will return you collection of parent elements and collection of parent nodes texts, which may not be desired. I would recommend lookup child element by id, since xhtml prescribes that elements ids are unique. Thus, an xpath for a parent div should better look like following:
//span[#id='_dcmanageinvestmentsportlet_WAR_ahdcmnginvportlet__FDROR_110hidden']/..

xpath get child node excluding parent

I'm looking for an xpath that will give me a child node only if the parent node doesn't equal a specific value. For example if I have an xml like the following:
<Grandpa><Dad><Son /></Dad><Son /></Grandpa>
I want to return the Son element outside the Dad element.
This Xpath selects those Son elements whose parent element is not named Dad:
//Son[local-name(..) != 'Dad']
So, applied to this XML:
<Grandpa><Dad><Son a="1"/></Dad><Son a="2"/></Grandpa>
It will select:
<Son a="2"/>

Retrieving a parent tag with a given attribute that contains a subelement by using XPath

How I can retrieve multiple DIVs (with a given class attribute "a") that contain a span tag with a class attribute "b" by using Xpath?
<div class='a'>
<span class='b'/>
</div>
The structure of my XML is not defined so basically the span could be at any level of the div and the div itself could be at any level of the XML tree.
This should work:
//div[#class='a'][span/#class='b']
// means search anywhere if it starts the expression.
If the span is deeper in the div, use descendant:: which can be shortened to // again:
//div[#class='a'][.//span/#class='b']

XPATH filter tag-less children

Is there any way to specify that I want to select only tag-less child elements (in the following example - "text")?
<div>
<p>...</p>
"text"
</div>
The text() function matches text nodes. Example: //div/text() — matches all text children within all div elements.
Use:
/*/text()[normalize-space()]
This selects all text nodes that are children of the top element of the document and that do not consist only of white-space characters.
In the concrete example this will select only the text node with string value:
'
"text"
'
The XPath expressions:
/*/text()
or
/div/text()
both select two text nodes, the first of which contains only white-space and the second is the same text node as above:
'
"text"
'
select only tag-less child elements
To me this sounds like selecting all elements that don't have other elements as children. But then again, "text" in your example is not an element, but a text node, so I'm not really sure what do you want to select...
Anyway, here is a solution for selecting such elements.
//*[not(*)]
Selects all elements that don't have an element as a child. Replace the first * with an element name if you only want to select certain elements that don't have child elements. Also note that using // is generally slow since it runs through the whole document. Consider using more specific path when possible (like /div/*[not(*)] in this case).

Resources