I'm interested in advice/pseudocode code/explanation rather than actual implementation.
- I'd like to go trough xml document, all of its nodes
- Check the node for attribute existence
Case if node doesn't have attribute, get/generate String with value of its xpath
Case if node does have attributes, iterate trough attribute list and create xpath for each attribute including the node as well.
Word of advice? Hopefully you will provide some useful intel
EDIT:
Reason for doing this is .. I'm writing automated tests in jmeter, so for every request I need to verify that request actually did its job so I'm asserting results by getting nodes values with xpath.(extra info - irrelevant)
When the request is small its not problem to create asserts by hand, but for larger ones its a really pain in the .. (extra info - irrelevant)
BOUNTY :
I'm looking for java approach
Goal
My goal is to achieve following from this ex xml file :
<root>
<elemA>one</elemA>
<elemA attribute1='first' attribute2='second'>two</elemA>
<elemB>three</elemB>
<elemA>four</elemA>
<elemC>
<elemB>five</elemB>
</elemC>
</root>
to produce the following :
//root[1]/elemA[1]='one'
//root[1]/elemA[2]='two'
//root[1]/elemA[2][@attribute1='first']
//root[1]/elemA[2][@attribute2='second']
//root[1]/elemB[1]='three'
//root[1]/elemA[3]='four'
//root[1]/elemC[1]/elemB[1]='five'
Explained :
- If node value/text is not null/zero, get xpath , add = 'nodevalue' for assertion purpose
- If node has attributes create assert for them too
BOUNTY UPDATE :
I found this example, it doesn't produce the correct results , but I'm looking something like this:
I have written a method to return the absolute path of an element in the Practical XML library. To give you an idea of how it works, here's an extract form one of the unit tests:
So, you could recurse through the document, apply your tests, and use this to return the XPath. Or, what is probably better, is that you could use the XPath-based assertions from that same library.
This code works with two assumptions: you aren't using namespaces and there are no mixed content elements. The namespace limitation isn't a serious one, but it'd make your XPath expression much harder to read, as every element would be something like
*:<name>[namespace-uri()='<nsuri>'][<index>]
, but otherwise it's easy to implement. Mixed content on the other hand would make the use of xpath very tedious, as you'd have to be able to individually address the second, third and so on text node within an element.With jOOX (a jquery API port to Java, disclaimer - I work for the company behind the library), you can almost achieve what you want in a single statement:
If document is your sample document:
This will produce
By "almost", I mean that jOOX does not (yet) support matching/mapping attributes. Hence, your attributes will not produce any output. This will be implemented in the near future, though.
Here is how this can be done with SAX:
It can be tested with:
This will produce the desired output:
Update:
@c0mrade has updated his question. Here is a solution to it:
This XSLT transformation:
when applied on the provided XML document:
produces exactly the wanted, correct result:
When applied to the newly-provided document by @c0mrade:
again the correct result is produced:
Explanation:
Only elements that have no children elements, or have attributes are matched and processed.
For any such element, if it doesn't have children-elements all of its ancestor-or self elements are processed in a specific mode, named
'path'
. Then the"='theValue'"
part is output and then a NL character.All attributes of the matched element are then processed.
Then finally, templates are applied to all children-elements.
Processing an element in the
'path'
mode is simple: A/
character and the name of the element are output. Then, if there are preceding siblings with the same name, a "[numPrecSiblings+1]` part is output.Processing of attributes is simple: First all
ancestor-or-self::
elements of its parent are processed in'path'
mode, then the [attrName=attrValue] part is output, followed by a NL character.Do note:
Names that are in a namespace are displayed without any problem and in their initial readable form.
To aid readability, an index of
[1]
is never displayed.Below is my initial answer (may be ignored)
Here is a pure XSLT 1.0 solution:
Below is a sample xml document and a stylesheet that takes a node-set parameter and produces one valid XPath expression for every member-node.
stylesheet (buildPath.xsl):
xml source (buildPath.xml):
Result:
something like that.
UPD: and concatenate final list in order to get final xpath. don't think attributes will be a problem.