2

In my JMeter test plan, I have a HttpRequest, I want to extract the link from its response only if the response code is 200. I can add an XPathExtractor post processor under HttpRequest and it works.

But I want to have an IfCondition first so that the extractor won't try to work on invalid content. But the IfController can't be added as a postprocessor.

Maybe I can have a BeanShell sampler to do it but I don't know how to use XPathExtractor in BeanShell.

Masud Jahan
  • 3,418
  • 2
  • 22
  • 35
user1532146
  • 184
  • 2
  • 14

1 Answers1

3
  1. "Short and easy" way - use an additional Sampler

    • Add If Controller after the HTTP Request
    • Use ${JMeterThread.last_sample_ok} as "Condition"
    • Put Beanshell Sampler under the If Controller
    • Use the following code in Beanshell Sampler "Script" area:

      SampleResult.setResponseData(ctx.getPreviousResult().getResponseData());
      
    • Put XPath Extractor as a child of the Beanshell Sampler

    The above Beanshell script will return the same response as preceding HTTP Request sampler

    1. "Long and hard" way - extract XPath directly in Beanshell.

      • Put Beanshell PostProcessor instead of XPath Extractor
      • Use the following script as a reference:

        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);
            }
        }
        

See How to Use BeanShell: JMeter's Favorite Built-in Component guide for more information on using Beanshell in JMeter scripts

Dmitri T
  • 159,985
  • 5
  • 83
  • 133