Ask a Question

wildcards in XPATH expressions?

mtroost
Occasional Contributor

wildcards in XPATH expressions?

Context: In a groovy script, a request is modified as in

holder1["//NodeA/ObjectID"]=project.getPropertyValue("objectid")
holder1["//NodeB/ObjectID"]=project.getPropertyValue("objectid")
...

You can see the node always starts with Node ans is then followed optionally by some string.

 

Question: Is it possible to make 1 XPATH expression taht matches all Node* named nodes? Is there a different way to achieve this in a different way?
The reason a groovy script is used is because lots of requests have to be changed and regular property transfer doesnt allow that (I presume).

6 REPLIES 6
nmrao
Community Hero

Re: wildcards in XPATH expressions?

See if this is what you are looking for http://stackoverflow.com/questions/21405267/xpath-using-regex-in-contains-function


Regards,
Rao.
mtroost
Occasional Contributor

Re: wildcards in XPATH expressions?

Thank you, I think it might be something just like that. Only I wouldnt know how to apply this to my situation. I also dont get what @id refers to.

holder1["//*[starts-with(@id,'Plaatsing') and ends-with(@id,'DAVINCIObjectID')"] =project.getPropertyValue("Plaatsing_objectid")

This grants me an error

XPath syntax error at char 70 on line 2 in {...ds-with(@id,'DAVINCIObjectI...}: expected "]", found " " error at line: 17
nmrao
Community Hero

Re: wildcards in XPATH expressions?

Not sure if you are still having the issue. If yes, then please post the xml and what node value you wanted to get.



Regards,
Rao.
mtroost
Occasional Contributor

Re: wildcards in XPATH expressions?

Consider the following XML

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:raad="http://raadpleegles.aanboddienst-01_00.davinci.ov.vlaanderen.be">
   <soapenv:Header/>
   <soapenv:Body>
      <raad:RaadpleegLes>
	 	<LesCreate>
	          <ObjectID>2d4e672c-8ebb-4a6d-9ee6-12eabf4b446a:14c47413430</ObjectID>
               <ConcurrencyToken>cdb93192-c8e9-4f85-9e52-54f2482b99c9:14c47413430</ConcurrencyToken>
	 	</LesCreate>
	 	<LesDelete>
	          <ObjectID>5d4e672c-8ebb-4a6d-9ee6-12eabf4b446a:14c47413430</ObjectID>
               <ConcurrencyToken>cdb93192-c8e9-4f85-9e52-54f2482b99c9:14c47413430</ConcurrencyToken>
	 	</LesDelete>
	 	<Les>
	          <ObjectID>hd4e672c-8ebb-4a6d-9ee6-12eabf4b446a:14c47413430</ObjectID>
               <ConcurrencyToken>cdb93192-c8e9-4f85-9e52-54f2482b99c9:14c47413430</ConcurrencyToken>
	 	</Les>
	 	<DONTCHANGE>
	          <ObjectID>hd4e672c-8ebb-4a6d-9ee6-12eabf4b446a:14c47413430</ObjectID>
               <ConcurrencyToken>cdb93192-c8e9-4f85-9e52-54f2482b99c9:14c47413430</ConcurrencyToken>
	 	</DONTCHANGE>
      </raad:RaadpleegLes>
   </soapenv:Body>
</soapenv:Envelope>

Several nodes name name starting with the string "Les". In those nodes Id like to change the value of their child node named "ObjectID". I can not do that for everything else like "DONTTOUCH". To substitute this script will work fine

import com.eviware.soapui.impl.wsdl.teststeps.*
import com.eviware.soapui.support.XmlHolder

def groovyUtils = new com.eviware.soapui.support.GroovyUtils( context ) 
def steps = testRunner.testCase.getTestStepsOfType( WsdlTestRequestStep.class )
def project = testRunner.testCase.testSuite.project
for (step in steps) {
	log.info step.name// + step.getLabel()
	def holder1 = groovyUtils.getXmlHolder( step.testRequest.requestContent )
	assert project.getPropertyValue("objectid") != null, "no objectid set"
	holder1["//Les/ObjectID"]=project.getPropertyValue("objectid")
	holder1["//LesCreate/ObjectID"]=project.getPropertyValue("objectid")
	holder1["//LesDelete/ObjectID"]=project.getPropertyValue("objectid")
	holder1.updateProperty()
	step.testRequest.setRequestContent (holder1.getXml());
}

In the example I included only 3 different names for the nodes to replace (Les, LesCreate, LesDelete). Now imagine there are not 3 but hundreds of possibilities, then how should one go about this?
Providing an expression the equivalent of //Les*/ObjectID would be my first attempt but I cant see how to include that in the supplied groovy script.

 

TanyaYatskovska
Community Manager

Re: wildcards in XPATH expressions?

Hi,

 

Perhaps, it makes sense to search for all ObjectID nodes whose parent contains Les. Something like this:

//ObjectID/parent::*[contains(name(), "Les")]
---------
Tanya Yatskovskaya
SmartBear Community and Education Manager

Did my reply answer your question? Give Kudos or Accept it as a Solution to help others. ⬇️⬇️⬇️
mtroost
Occasional Contributor

Re: wildcards in XPATH expressions?

It looks like it makes sense, just like post#2. But the problem is still the same: I cant (or dont know how to) apply it in this situation.

 

Extended the code:

 

import com.eviware.soapui.impl.wsdl.teststeps.*
import com.eviware.soapui.support.XmlHolder

def groovyUtils = new com.eviware.soapui.support.GroovyUtils( context ) 
def steps = testRunner.testCase.getTestStepsOfType( WsdlTestRequestStep.class )
def project = testRunner.testCase.testSuite.project
for (step in steps) {
	log.info step.name// + step.getLabel()
	def holder1 = groovyUtils.getXmlHolder( step.testRequest.requestContent )
	assert project.getPropertyValue("objectid") != null, "no objectid set"
//	holder1["//Les/ObjectID"]=project.getPropertyValue("objectid")
//	holder1["//LesCreate/ObjectID"]=project.getPropertyValue("objectid")
//	holder1["//LesDelete/ObjectID"]=project.getPropertyValue("objectid")
	def nodes = holder1.getDomNodes("//ObjectID/parent::*[contains(name(), \"Les\")]")
	log.info "new value "+project.getPropertyValue("objectid")
	for(int i = 0; i < nodes.length-1 ; i++) {
		def elems = nodes[i].getChildNodes();
		for(int j = 0; j < elems.length-1 ; j++) {
			def child = elems.item(j);
			log.info "child $j "+ child
			if( child.getNodeName() == "ObjectID") {
				log.info "YES! we got one! Now the new value: "
				child.setNodeValue(project.getPropertyValue("objectid"))
				log.info child.getNodeValue()
			}
		}
	}
	holder1.updateProperty()
	step.testRequest.setRequestContent (holder1.getXml());
}

Problems:

 

1) The last print  

log.info child.getNodeValue()

does print null. And no, the project.getPropertyValue("objectid") does not return null.

2) the XML code of the test request has not changed.

3) The node "Les" does NOT match the Xpath expression

4) It is slightly better as parsing the whole document yourself but.... barely. It is a mess compared to a simple sed -e 's/Les(.*)\/ObjectID/.... . You get the meaning, in lots of languages this is a one statement string replace with a reg ex.

cancel
Showing results for 
Search instead for 
Did you mean: