仅当 Http 响应代码为 200 时,如何获取 XPath Extractor 提取 xml 元素?
How to let XPathExtractor extract xml element only if Http response code is 200?
在我的 JMeter 测试计划中,我有一个 HttpRequest,我想仅在响应代码为 200
时从其响应中提取 link。
我可以在 HttpRequest 下添加一个 XPathExtractor
post 处理器,它可以工作。
但我想先有一个 IfCondition
,这样提取器就不会尝试处理无效内容。但是不能将 IfController 添加为 post 处理器。
也许我可以 BeanShell sampler
来做,但我不知道如何在 BeanShell 中使用 XPathExtractor。
"Short and easy" 方法 - 使用额外的采样器
- 在 HTTP 请求后添加 If Controller
- 将
${JMeterThread.last_sample_ok}
用作"Condition"
- 将Beanshell Sampler放在If控制器下
在Beanshell Sampler "Script"区使用如下代码:
SampleResult.setResponseData(ctx.getPreviousResult().getResponseData());
将 XPath Extractor 作为 Beanshell Sampler 的子项
上面的 Beanshell 脚本将 return 与前面的 HTTP 请求采样器
相同的响应
"Long and hard" 方式 - 直接在 Beanshell 中提取 XPath。
- 用 Beanshell PostProcessor 代替 XPath Extractor
参考以下脚本:
import org.apache.jmeter.util.PropertiesBasedPrefixResolver;
import org.apache.jmeter.util.XPathUtil;
import org.apache.xpath.XPathAPI;
import org.apache.xpath.objects.XObject;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
InputStream in = new ByteArrayInputStream(prev.getResponseData());
boolean useNameSpace = false;
boolean isTolerant = true;
boolean isQuiet = true;
boolean showWarnings = true;
boolean reportErrors = true;
boolean isXML = false;
boolean isDownloadDTDs = false;
if (prev.isResponseCodeOK()) {
InputStream in = new ByteArrayInputStream(prev.getResponseData());
boolean useNameSpace = false;
boolean isTolerant = true;
boolean isQuiet = true;
boolean showWarnings = true;
boolean reportErrors = true;
boolean isXML = false;
boolean isDownloadDTDs = false;
String query = "//a[text()='JMeter FAQ (Wiki)']";
List matchStrings = new ArrayList();
//matchStrings.add("-1");
boolean returnFragment = false;
Document doc = XPathUtil.makeDocument(in, false, false, useNameSpace, isTolerant, isQuiet, showWarnings, reportErrors
, isXML, isDownloadDTDs);
String val = null;
XObject xObject = XPathAPI.eval(doc, query, new PropertiesBasedPrefixResolver(doc.getDocumentElement());
int objectType = xObject.getType();
if (objectType == xObject.CLASS_NODESET) {
NodeList matches = xObject.nodelist();
int length = matches.getLength();
for (int i = 0; i < length; ++i) {
Node match = matches.item(i);
if (match instanceof Element) {
if (returnFragment) {
StringWriter sw = new StringWriter();
Transformer t = TransformerFactory.newInstance().newTransformer();
t.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
t.transform(new DOMSource(match), new StreamResult(sw));
val = sw.toString();
} else {
Node firstChild = match.getFirstChild();
if (firstChild != null) {
val = firstChild.getNodeValue();
} else {
val = match.getNodeValue();
}
}
} else {
val = match.getNodeValue();
}
matchStrings.add(val);
}
} else if (objectType != xObject.CLASS_NULL && objectType != xObject.CLASS_UNKNOWN && objectType != xObject.CLASS_UNRESOLVEDVARIABLE) {
val = xObject.toString();
matchStrings.add(val);
} else {
log.warn("Unexpected object type: " + xObject.getTypeString() + " returned for: " + query);
}
for (String match : matchStrings) {
log.info("Match -----> " + match);
}
}
有关在 JMeter 脚本中使用 Beanshell 的更多信息,请参阅 How to Use BeanShell: JMeter's Favorite Built-in Component 指南
在我的 JMeter 测试计划中,我有一个 HttpRequest,我想仅在响应代码为 200
时从其响应中提取 link。
我可以在 HttpRequest 下添加一个 XPathExtractor
post 处理器,它可以工作。
但我想先有一个 IfCondition
,这样提取器就不会尝试处理无效内容。但是不能将 IfController 添加为 post 处理器。
也许我可以 BeanShell sampler
来做,但我不知道如何在 BeanShell 中使用 XPathExtractor。
"Short and easy" 方法 - 使用额外的采样器
- 在 HTTP 请求后添加 If Controller
- 将
${JMeterThread.last_sample_ok}
用作"Condition" - 将Beanshell Sampler放在If控制器下
在Beanshell Sampler "Script"区使用如下代码:
SampleResult.setResponseData(ctx.getPreviousResult().getResponseData());
将 XPath Extractor 作为 Beanshell Sampler 的子项
上面的 Beanshell 脚本将 return 与前面的 HTTP 请求采样器
相同的响应"Long and hard" 方式 - 直接在 Beanshell 中提取 XPath。
- 用 Beanshell PostProcessor 代替 XPath Extractor
参考以下脚本:
import org.apache.jmeter.util.PropertiesBasedPrefixResolver; import org.apache.jmeter.util.XPathUtil; import org.apache.xpath.XPathAPI; import org.apache.xpath.objects.XObject; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.Node; import org.w3c.dom.NodeList; import javax.xml.transform.OutputKeys; import javax.xml.transform.Transformer; import javax.xml.transform.TransformerFactory; import javax.xml.transform.dom.DOMSource; import javax.xml.transform.stream.StreamResult; InputStream in = new ByteArrayInputStream(prev.getResponseData()); boolean useNameSpace = false; boolean isTolerant = true; boolean isQuiet = true; boolean showWarnings = true; boolean reportErrors = true; boolean isXML = false; boolean isDownloadDTDs = false; if (prev.isResponseCodeOK()) { InputStream in = new ByteArrayInputStream(prev.getResponseData()); boolean useNameSpace = false; boolean isTolerant = true; boolean isQuiet = true; boolean showWarnings = true; boolean reportErrors = true; boolean isXML = false; boolean isDownloadDTDs = false; String query = "//a[text()='JMeter FAQ (Wiki)']"; List matchStrings = new ArrayList(); //matchStrings.add("-1"); boolean returnFragment = false; Document doc = XPathUtil.makeDocument(in, false, false, useNameSpace, isTolerant, isQuiet, showWarnings, reportErrors , isXML, isDownloadDTDs); String val = null; XObject xObject = XPathAPI.eval(doc, query, new PropertiesBasedPrefixResolver(doc.getDocumentElement()); int objectType = xObject.getType(); if (objectType == xObject.CLASS_NODESET) { NodeList matches = xObject.nodelist(); int length = matches.getLength(); for (int i = 0; i < length; ++i) { Node match = matches.item(i); if (match instanceof Element) { if (returnFragment) { StringWriter sw = new StringWriter(); Transformer t = TransformerFactory.newInstance().newTransformer(); t.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes"); t.transform(new DOMSource(match), new StreamResult(sw)); val = sw.toString(); } else { Node firstChild = match.getFirstChild(); if (firstChild != null) { val = firstChild.getNodeValue(); } else { val = match.getNodeValue(); } } } else { val = match.getNodeValue(); } matchStrings.add(val); } } else if (objectType != xObject.CLASS_NULL && objectType != xObject.CLASS_UNKNOWN && objectType != xObject.CLASS_UNRESOLVEDVARIABLE) { val = xObject.toString(); matchStrings.add(val); } else { log.warn("Unexpected object type: " + xObject.getTypeString() + " returned for: " + query); } for (String match : matchStrings) { log.info("Match -----> " + match); } }
有关在 JMeter 脚本中使用 Beanshell 的更多信息,请参阅 How to Use BeanShell: JMeter's Favorite Built-in Component 指南