In my JMeter scenario I'm testing SOAP webservices. I send the initial request to webservice S1 and then use response from it to build request to S2. The response from S1 comes in the form:
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<s:response xmlns:s="http://custom.namespace.com/namespace">
...
<s:responseDetails>
<s:detail1>some info</s:detail>
<s:detail2>another info<s:detail2>
...
</s:responseDetails>
</s:response>
</soap:Body>
</soap:Envelope>
I need to use everything inside <s:responseDetails>
to build request to S2 but wrapped inside different xml element:
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:s="http://custom.namespace.com/namespace">
<soap:Body>
<s:request>
<s:details>
<s:detail1>some info</s:detail>
<s:detail2>another info<s:detail2>
...
</s:details>
</s:request>
</soap:Body>
</soap:Envelope>
Note element <s:details>
in request instead of <s:responseDetails>
.
I started with XPath extractor hoping to use XPath expression to put everything under <s:responseDetails>
tag into JMeter variable:
//*[local-name()='responseDetails']/node()
- gives me a set of JMeter variables with different children of <s:responseDetails>
, while I want them to be in one variable//*[local-name()='responseDetails']
- gives me the entire node <s:responseDetails>
which I can't use because of the presence of root tag <s:responseDetails>
, which I need to replace with <s:details>
What is the proper expression to get everything inside <s:responseDetails>
into variable, so that I can later use
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:s="http://custom.namespace.com/namespace">
<soap:Body>
<s:request>
<s:details>
${details}
</s:details>
</s:request>
</soap:Body>
</soap:Envelope>
Or maybe there is another way to solve my problem?
Do the following:
1) Add XPath Extractor as you did with:
2) Add a Beanshell Sampler with:
String fragment = vars.get("responseFragment");
// Improve this replacement by regexp to avoid side effects
String newFragment = fragment.replace("responseDetails","details");
vars.put("modifiedFragment", newFragment);
3) Then use : ${modifiedFragment}
Note that Beanshell sampler will slightly degrade JMeter performances but it should be reasonable.
Note that you can replace Beanshell sampler with JSR 223 with groovy underlying language and script in external file.
Using JMeter > 2.7 version performances will be better than beanshell solution because new version of JMeter introduces a new caching mechanism that will "compile" the Groovy script and make it almost as efficient as Java class.
As of 3 september 2012, this mechanism is available in JMeter Nightly build.
JMeter Test Plan example:
<?xml version="1.0" encoding="UTF-8"?>
<jmeterTestPlan version="1.2" properties="2.3" jmeter="2.8-SNAPSHOT.20120903">
<hashTree>
<TestPlan guiclass="TestPlanGui" testclass="TestPlan" testname="Test Plan" enabled="true">
<stringProp name="TestPlan.comments"></stringProp>
<boolProp name="TestPlan.functional_mode">false</boolProp>
<boolProp name="TestPlan.serialize_threadgroups">false</boolProp>
<elementProp name="TestPlan.user_defined_variables" elementType="Arguments" guiclass="ArgumentsPanel" testclass="Arguments" testname="User Defined Variables" enabled="true">
<collectionProp name="Arguments.arguments"/>
</elementProp>
<stringProp name="TestPlan.user_define_classpath"></stringProp>
</TestPlan>
<hashTree>
<ThreadGroup guiclass="ThreadGroupGui" testclass="ThreadGroup" testname="Thread Group" enabled="true">
<stringProp name="ThreadGroup.on_sample_error">continue</stringProp>
<elementProp name="ThreadGroup.main_controller" elementType="LoopController" guiclass="LoopControlPanel" testclass="LoopController" testname="Loop Controller" enabled="true">
<boolProp name="LoopController.continue_forever">false</boolProp>
<stringProp name="LoopController.loops">1</stringProp>
</elementProp>
<stringProp name="ThreadGroup.num_threads">1</stringProp>
<stringProp name="ThreadGroup.ramp_time">1</stringProp>
<longProp name="ThreadGroup.start_time">1346673693000</longProp>
<longProp name="ThreadGroup.end_time">1346673693000</longProp>
<boolProp name="ThreadGroup.scheduler">false</boolProp>
<stringProp name="ThreadGroup.duration"></stringProp>
<stringProp name="ThreadGroup.delay"></stringProp>
</ThreadGroup>
<hashTree>
<JavaSampler guiclass="JavaTestSamplerGui" testclass="JavaSampler" testname="Java Request" enabled="true">
<elementProp name="arguments" elementType="Arguments" guiclass="ArgumentsPanel" testclass="Arguments" enabled="true">
<collectionProp name="Arguments.arguments">
<elementProp name="Sleep_Time" elementType="Argument">
<stringProp name="Argument.name">Sleep_Time</stringProp>
<stringProp name="Argument.value">100</stringProp>
<stringProp name="Argument.metadata">=</stringProp>
</elementProp>
<elementProp name="Sleep_Mask" elementType="Argument">
<stringProp name="Argument.name">Sleep_Mask</stringProp>
<stringProp name="Argument.value">0xFF</stringProp>
<stringProp name="Argument.metadata">=</stringProp>
</elementProp>
<elementProp name="Label" elementType="Argument">
<stringProp name="Argument.name">Label</stringProp>
<stringProp name="Argument.value">OK</stringProp>
<stringProp name="Argument.metadata">=</stringProp>
</elementProp>
<elementProp name="ResponseCode" elementType="Argument">
<stringProp name="Argument.name">ResponseCode</stringProp>
<stringProp name="Argument.value">200</stringProp>
<stringProp name="Argument.metadata">=</stringProp>
</elementProp>
<elementProp name="ResponseMessage" elementType="Argument">
<stringProp name="Argument.name">ResponseMessage</stringProp>
<stringProp name="Argument.value">200</stringProp>
<stringProp name="Argument.metadata">=</stringProp>
</elementProp>
<elementProp name="Status" elementType="Argument">
<stringProp name="Argument.name">Status</stringProp>
<stringProp name="Argument.value">OK</stringProp>
<stringProp name="Argument.metadata">=</stringProp>
</elementProp>
<elementProp name="SamplerData" elementType="Argument">
<stringProp name="Argument.name">SamplerData</stringProp>
<stringProp name="Argument.value"></stringProp>
<stringProp name="Argument.metadata">=</stringProp>
</elementProp>
<elementProp name="ResultData" elementType="Argument">
<stringProp name="Argument.name">ResultData</stringProp>
<stringProp name="Argument.value"><soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"> <soap:Body> <s:response xmlns:s="http://custom.namespace.com/namespace"> <s:responseDetails> <s:detail1>some info</s:detail1> <s:detail2>another info</s:detail2> </s:responseDetails> </s:response> </soap:Body> </soap:Envelope></stringProp>
<stringProp name="Argument.metadata">=</stringProp>
</elementProp>
</collectionProp>
</elementProp>
<stringProp name="classname">org.apache.jmeter.protocol.java.test.JavaTest</stringProp>
</JavaSampler>
<hashTree>
<XPathExtractor guiclass="XPathExtractorGui" testclass="XPathExtractor" testname="XPath Extractor" enabled="true">
<stringProp name="XPathExtractor.default"></stringProp>
<stringProp name="XPathExtractor.refname">TOTO</stringProp>
<stringProp name="XPathExtractor.xpathQuery">//s:response/s:responseDetails</stringProp>
<boolProp name="XPathExtractor.validate">false</boolProp>
<boolProp name="XPathExtractor.tolerant">false</boolProp>
<boolProp name="XPathExtractor.namespace">true</boolProp>
<boolProp name="XPathExtractor.whitespace">true</boolProp>
</XPathExtractor>
<hashTree/>
</hashTree>
<DebugSampler guiclass="TestBeanGUI" testclass="DebugSampler" testname="Debug Sampler" enabled="true">
<boolProp name="displayJMeterProperties">false</boolProp>
<boolProp name="displayJMeterVariables">true</boolProp>
<boolProp name="displaySystemProperties">false</boolProp>
</DebugSampler>
<hashTree/>
<ResultCollector guiclass="ViewResultsFullVisualizer" testclass="ResultCollector" testname="View Results Tree" enabled="true">
<boolProp name="ResultCollector.error_logging">false</boolProp>
<objProp>
<name>saveConfig</name>
<value class="SampleSaveConfiguration">
<time>true</time>
<latency>true</latency>
<timestamp>true</timestamp>
<success>true</success>
<label>true</label>
<code>true</code>
<message>false</message>
<threadName>true</threadName>
<dataType>false</dataType>
<encoding>false</encoding>
<assertions>true</assertions>
<subresults>false</subresults>
<responseData>false</responseData>
<samplerData>false</samplerData>
<xml>false</xml>
<fieldNames>false</fieldNames>
<responseHeaders>false</responseHeaders>
<requestHeaders>false</requestHeaders>
<responseDataOnError>false</responseDataOnError>
<saveAssertionResultsFailureMessage>false</saveAssertionResultsFailureMessage>
<assertionsResultsToSave>0</assertionsResultsToSave>
<bytes>true</bytes>
<hostname>true</hostname>
<threadCounts>true</threadCounts>
<sampleCount>true</sampleCount>
</value>
</objProp>
<stringProp name="filename"></stringProp>
</ResultCollector>
<hashTree/>
</hashTree>
</hashTree>
</hashTree>
</jmeterTestPlan>
An other way:
1) Add XPath Extractor as you did with:
2) Add a Beanshell Sampler with:
int number = Integer.parseInt(vars.get("fullAnswer_matchNr"));
StringBuilder builder = new StringBuilder();
for(int i=0;i<number;i++) {
builder.append(vars.get("fullAnswer_"+(i+1)));
}
vars.put("body", builder.toString());
3) use body
This one is a little cleaner as there is no replacement
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With