Get all the child elements of parent node using xpath expression OSB - xpath

I am using OSB and have one long XML containing parent and child node.
This is my XML
<XML>
<RefreshLaborApproval2RSP xmlns:XPathFunction="http://www.oracle.com/XSL/Transform/java/mol.prc.labourapproval.XPathFunction" xmlns:tsd="http://namespaces.softwareag.com/tamino/TaminoSchemaDefinition">
<ERRORCODE>
<VALUE>dfdfdf</VALUE>
</ERRORCODE>
<LABORRECORDS>
<LABORNAT>
<VALUE>569</VALUE>
</LABORNAT>
</LABORRECORDS>
<LABORRECORDS>
<LABORNAT>
<VALUE>218</VALUE>
</LABORNAT>
</LABORRECORDS>
</RefreshLaborApproval2RSP>
</XML>
When I use expression XML/* its gives me the whole XML from <RefreshLaborApproval2RSP> to </RefreshLaborApproval2RSP> and kept the same in one variable called xmlparentNode.
And then when I use $xmlparentNode/LABORRECORDS then I get only istLABORRECORDS child element like below.
<LABORRECORDS>
<LABORNAT>
<VALUE>569</VALUE>
</LABORNAT>
</LABORRECORDS>
But I want all <LABORRECORDS> child elements.

I dont know what exacly you want achieve, but you can:
Assign variable xmlparentNode,
Use For Each for example:
a) For Each Variable: Laborrecords
b) XPath: ./LABORRECORDS
c) In Variable: xmlparentNode
d) Index Variable: index
e) Count Variable: count
And then inside For Each do Assign expression: $Laborrecords in variable to get first value, then second.
Do some inserts or something with it.
I do not know if this will solve your problem.

The XML expression that you are using is right.
If the XML elements are very long and you are using variable window (during debugging) to see the element returned, there could be a possible chance to data loss.

Related

VB NET XPath won't select a node based on a value

I have a node on an XML file for which I need to select. To select, I have to look at one of the element's value. Once selected, I will then arrange for the entire node to be deleted from the file.
We have a framework that deals with the selecting of nodes however I currently receive the following error: Expression must evaluate to a node-set.
All the framework does is takes in the XMLElement and XPath, and uses what looks to be a defined function named .selectNode(xPath) to find the node. This is what throws the above error.
My XML Data set(which is the XMLElement) looks like this:
<topParent value1="a" value2 = "b">
<att1 value3="c" value4 = "d">
<myline data="e" moredata="f" />
<myline data="g" moredata="h" />
</att1>
</topParent>
and my xPath for selecting looks like : //myline/[#moredata='h']
The idea is to select "myline" node when "moreData" equals h
I've only come across XPath in the last few hours but I can't see why this node isn't being selected.
You shouldn't put a slash before a predicate. It's wrong syntax.
Just use
//myline[#moredata='h']
to select all the myline elements which satisfy the condition.

Xpath multiply formatted output

Have a many entries in an xml file and have xpath with condition:
/XMLReport/Report/PreflightResult/PreflightResultEntry[
#type = 'Check' and #level = 'warning']/PreflightResultEntryMessage/Message/text()
The output is:
onetwothreefour... and more
I need separation
'---' one---two---three---four
or
[enter]
one
two
three
four
Its possible ?
Why you bound XPath expression inside single quote ':
Use this:
string-join(/XMLReport/Report/PreflightResult/PreflightResultEntry[#type = 'Check' and #level = 'warning']/PreflightResultEntryMessage/Message/text(), '---')
Your XPath expression is actually returning a set of text nodes. The way these are displayed depends on the calling application (which you haven't told us anything about). I think your options are (a) change the way the calling application displays the result, or (b) if you're using XPath 2.0+, use the string-join() function to return the result as a string, formatted any way you like within the XPath expression itself.

BaseX XQuery error: root(): no context value bound

I am trying to run the following XQuery expression in BaseX to extract elements between two succeeding headings. (as an article section).
xquery for $x in doc("test.xq")//h2,
$y in $x/following-sibling::h2[1]
return //*[$x/following::* and $y/preceding::*]
But it gives the error
Error:
Stopped at D:/Program Files/BaseX/data/test.xq, 1/74:
[XPDY0002] root(): no context value bound.
By the expression I mean if $x is heading and $y is the first heading following $x, then select the common text for $x/following::* and $y/preceding::*
However I am not sure my expression works, but my question here is how can execute my intended query without error?
If you have also an expression which works for my need, that is welcomed.
[...] to extract elements between two succeeding headings [...]
You need something more like:
for $x in doc("test.xq")//h2
return $x/following-sibling::*[preceding-sibling::h2[1] is $x]
but on its own it won't give you anything useful because the XPath and XQuery data model only has flat sequences, not "multi-dimensional arrays". When you have a for that returns a sequence of values for each "iteration", the overall result of the for expression is the concatenation of all the result sequences, so as written above this expression will simply return you all the elements in every "section" in a single flat list. If you want to group the elements by section then you'd need to construct a new XML element for each group
for $x in doc("test.xq")//h2
return
<section>{$x/following-sibling::*[preceding-sibling::h2[1] is $x]}</section>
The error (as documented here) comes from this expression:
//*[$x/following::* and $y/preceding::*]
which begins with //. The abbreviation // stands for /descendant-or-self::node()/, which of course begins with /. The XPath standard says:
A / by itself selects the root node of the document containing the
context node. If it is followed by a relative location path, then the
location path selects the set of nodes that would be selected by the
relative location path relative to the root node of the document
containing the context node.
But from what you've shown us, there is nothing indicating that you've established a context node. So XPath doesn't have any way to know what document contains the context node. That's what the error message is referring to when it says
root(): no context value bound
To fix the error, you could precede the // with an explicit doc(...) or any other explicit way to set the context:
doc("test.xq")//*[$x/following::* and $y/preceding::*]
or
root($x)//*[$x/following::* and $y/preceding::*]
This should get rid of the error, but as Ian Roberts has written, it won't give you the result you want. See his answer for that.

Selenium find element which have no attributes but have parents with same attributes

I am trying to find XPath of an element which has no attribute. It can only be identified by its parent's attribute. However, the parent also does not have unique attribute.
Eg: //*[#id="btn"][1]/ul/li[2]/a/span
Here there are 2 elements with id=btn. How do i get the 2nd element. The above syntax gives me 1st element.. However if i use:
//*[#id="btn"][2]/ul/li[2]/a/span
I get an error message
"The xpath expression '//*[#id="btn"][2]/ul/li[2]/a/span' cannot be evaluated or does not result in a WebElement "
Try this, you select those two first, then use brackets around and index them.
(//*[#id="btn"]/ul/li[2]/a/span)[2]
By the way, it's not a good practice to have multiple elements sharing same ids, if you are the developer, may consider change them.

XPath concat multiple nodes

I'm not very familiar with xpath. But I was working with xpath expressions and setting them in a database. Actually it's just the BAM tool for biztalk.
Anyway, I have an xml which could look like:
<File>
<Element1>element1<Element1>
<Element2>element2<Element2>
<Element3>
<SubElement>sub1</SubElement>
<SubElement>sub2</SubElement>
<SubElement>sub3</SubElement>
<Element3>
</File>
I was wondering if there is a way to use an xpath expression of getting all the SubElements concatted? At the moment, I am using:
/*[local-name()='File']/*[local-name()='Element3']/*[local-name()='SubElement']
This works if it only has one index. But apparently my xml sometimes has more nodes, so it gives NULL. I could just use
/*[local-name()='File']/*[local-name()='Element3']/*[local-name()='SubElement'][0]
but I need all the nodes. Is there a way to do this?
Thanks a lot!
Edit: I changed the XML, I was wrong, it's different, it should look like this:
<item>
<element1>el1</element1>
<element2>el2</element2>
<element3>el3</element3>
<element4>
<subEl1>subel1a</subEl1>
<subEl2>subel2a</subEl2>
</element4>
<element4>
<subEl1>subel1b</subEl1>
<subEl2>subel2b</subEl2>
</element4>
</item>
And I need to have a one line code to get a result like: "subel2a subel2b";
I need the one line because I set this xpath expression as an xml attribute (not my choice, it's specified). I tried string-join but it's not really working.
string-join(/file/Element3/SubElement, ',')
/File/Element3/SubElement will match all of the SubElement elements in your sample XML. What are you using to evaluate it?
If your evaluation method is subject to the "first node rule", then it will only match the first one. If you are using a method that returns a nodeset, then it will return all of them.
You can get all SubElements by using:
//SubElement
But this won't keep them grouped together how you want. You will want to do a query for all elements that contain a SubElement (basically do a search for the parent of any SubElements).
//parent::SubElement
Once you have that, you could (depending on your programming language) loop through the parents and concatenate the SubElements.

Resources