Author: sebb
Date: Mon Feb  1 00:17:15 2010
New Revision: 905149

URL: http://svn.apache.org/viewvc?rev=905149&view=rev
Log:
Add Sampler scope selection to XPathExtractor

Modified:
    jakarta/jmeter/trunk/docs/images/screenshots/xpath_extractor.png
    
jakarta/jmeter/trunk/src/components/org/apache/jmeter/extractor/RegexExtractor.java
    
jakarta/jmeter/trunk/src/components/org/apache/jmeter/extractor/XPathExtractor.java
    
jakarta/jmeter/trunk/src/components/org/apache/jmeter/extractor/gui/RegexExtractorGui.java
    
jakarta/jmeter/trunk/src/components/org/apache/jmeter/extractor/gui/XPathExtractorGui.java
    
jakarta/jmeter/trunk/src/core/org/apache/jmeter/testelement/AbstractScopedTestElement.java
    
jakarta/jmeter/trunk/test/src/org/apache/jmeter/extractor/TestXPathExtractor.java
    jakarta/jmeter/trunk/xdocs/changes.xml
    jakarta/jmeter/trunk/xdocs/images/screenshots/xpath_extractor.png
    jakarta/jmeter/trunk/xdocs/usermanual/component_reference.xml

Modified: jakarta/jmeter/trunk/docs/images/screenshots/xpath_extractor.png
URL: 
http://svn.apache.org/viewvc/jakarta/jmeter/trunk/docs/images/screenshots/xpath_extractor.png?rev=905149&r1=905148&r2=905149&view=diff
==============================================================================
Binary files - no diff available.

Modified: 
jakarta/jmeter/trunk/src/components/org/apache/jmeter/extractor/RegexExtractor.java
URL: 
http://svn.apache.org/viewvc/jakarta/jmeter/trunk/src/components/org/apache/jmeter/extractor/RegexExtractor.java?rev=905149&r1=905148&r2=905149&view=diff
==============================================================================
--- 
jakarta/jmeter/trunk/src/components/org/apache/jmeter/extractor/RegexExtractor.java
 (original)
+++ 
jakarta/jmeter/trunk/src/components/org/apache/jmeter/extractor/RegexExtractor.java
 Mon Feb  1 00:17:15 2010
@@ -177,17 +177,7 @@
     }
     
     private List<MatchResult> processMatches(String regex, SampleResult 
result, int matchNumber) {
-        List<SampleResult> sampleList = new ArrayList<SampleResult>();
-
-        String scope = fetchScope();
-        if (isScopeParent(scope) || isScopeAll(scope)) {
-            sampleList.add(result);
-        }
-        if (isScopeChildren(scope) || isScopeAll(scope)) {
-            for (SampleResult subResult : result.getSubResults()) {
-                sampleList.add(subResult);
-            }
-        }
+        List<SampleResult> sampleList = getSampleList(result);
 
         if (log.isDebugEnabled()) {
             log.debug("Regex = " + regex);

Modified: 
jakarta/jmeter/trunk/src/components/org/apache/jmeter/extractor/XPathExtractor.java
URL: 
http://svn.apache.org/viewvc/jakarta/jmeter/trunk/src/components/org/apache/jmeter/extractor/XPathExtractor.java?rev=905149&r1=905148&r2=905149&view=diff
==============================================================================
--- 
jakarta/jmeter/trunk/src/components/org/apache/jmeter/extractor/XPathExtractor.java
 (original)
+++ 
jakarta/jmeter/trunk/src/components/org/apache/jmeter/extractor/XPathExtractor.java
 Mon Feb  1 00:17:15 2010
@@ -22,6 +22,8 @@
 import java.io.Serializable;
 import java.io.UnsupportedEncodingException;
 import java.io.StringWriter;
+import java.util.ArrayList;
+import java.util.List;
 
 import javax.xml.parsers.ParserConfigurationException;
 import javax.xml.transform.TransformerException;
@@ -29,7 +31,7 @@
 import org.apache.jmeter.assertions.AssertionResult;
 import org.apache.jmeter.processor.PostProcessor;
 import org.apache.jmeter.samplers.SampleResult;
-import org.apache.jmeter.testelement.AbstractTestElement;
+import org.apache.jmeter.testelement.AbstractScopedTestElement;
 import org.apache.jmeter.testelement.property.BooleanProperty;
 import org.apache.jmeter.threads.JMeterContext;
 import org.apache.jmeter.threads.JMeterVariables;
@@ -77,7 +79,7 @@
  *
  * See Bugzilla: 37183
  */
-public class XPathExtractor extends AbstractTestElement implements
+public class XPathExtractor extends AbstractScopedTestElement implements
         PostProcessor, Serializable {
     private static final Logger log = LoggingManager.getLoggerForClass();
 
@@ -105,6 +107,10 @@
         return new StringBuilder(s1).append("_").append(s2).toString(); // 
$NON-NLS-1$
     }
 
+    private String concat(String s1, int i){
+        return new StringBuilder(s1).append("_").append(i).toString(); // 
$NON-NLS-1$
+    }
+
     /**
      * Do the job - extract value from (X)HTML response using XPath Query.
      * Return value as variable defined by REFNAME. Returns DEFAULT value
@@ -119,12 +125,42 @@
         JMeterVariables vars = context.getVariables();
         String refName = getRefName();
         vars.put(refName, getDefaultValue());
-        vars.put(concat(refName,MATCH_NR), "0"); // In case parse fails // 
$NON-NLS-1$
+        final String matchNR = concat(refName,MATCH_NR);
+        int prevCount=0; // number of previous matches
+        try {
+            prevCount=Integer.parseInt(vars.get(matchNR));
+        } catch (NumberFormatException e) {
+            // ignored
+        }
+        vars.put(matchNR, "0"); // In case parse fails // $NON-NLS-1$
         vars.remove(concat(refName,"1")); // In case parse fails // $NON-NLS-1$
 
+        List<SampleResult> samples = getSampleList(previousResult);
         try{
-            Document d = parseResponse(previousResult);
-            getValuesForXPath(d,getXPathQuery(),vars, refName);
+            List<String> matches = new ArrayList<String>();
+            for (SampleResult res : samples) {
+                Document d = parseResponse(res);
+                getValuesForXPath(d,getXPathQuery(),matches);
+            }
+            final int matchCount = matches.size();
+            vars.put(matchNR, String.valueOf(matchCount));
+            if (matchCount > 0){
+                String value = matches.get(0);
+                if (value != null) {
+                    vars.put(refName, value);
+                }
+                for(int i=0; i < matchCount; i++){
+                    value = matches.get(i);
+                    if (value != null) {
+                        vars.put(concat(refName,i+1),matches.get(i));          
          
+                    }
+                }
+            }
+            vars.remove(concat(refName,matchCount+1)); // Just in case
+            // Clear any other remaining variables
+            for(int i=matchCount+2; i <= prevCount; i++) {
+                vars.remove(concat(refName,i));                
+            }
         }catch(IOException e){// e.g. DTD not reachable
             final String errorMessage = "IOException on ("+getXPathQuery()+")";
             log.error(errorMessage,e);
@@ -253,7 +289,6 @@
     {
       //TODO: validate contentType for reasonable types?
 
-      //TODO: is it really necessary to recode the data?
       // NOTE: responseData encoding is server specific
       //       Therefore we do byte -> unicode -> byte conversion
       //       to ensure UTF-8 encoding as required by XPathUtil
@@ -269,20 +304,20 @@
 
     /**
      * Extract value from Document d by XPath query.
-     * @param d
-     * @param query
+     * @param d the document
+     * @param query the query to execute
+     * @param matchStrings list of matched strings (may include nulls)
+     * 
      * @throws TransformerException
      */
-    private void getValuesForXPath(Document d,String query, JMeterVariables 
vars, String refName)
-     throws TransformerException
-    {
+    private void getValuesForXPath(Document d,String query, List<String> 
matchStrings)
+        throws TransformerException {
         String val = null;
-         XObject xObject = XPathAPI.eval(d, query);
+        XObject xObject = XPathAPI.eval(d, query);
         final int objectType = xObject.getType();
         if (objectType == XObject.CLASS_NODESET) {
             NodeList matches = xObject.nodelist();
             int length = matches.getLength();
-            vars.put(concat(refName,MATCH_NR), String.valueOf(length));
             for (int i = 0 ; i < length; i++) {
                 Node match = matches.item(i);
                 if ( match instanceof Element){
@@ -300,25 +335,16 @@
                 } else {
                    val = match.getNodeValue();
                 }
-                if ( val!=null){
-                    if (i==0) {// Treat 1st match specially
-                        vars.put(refName,val);
-                    }
-                    vars.put(concat(refName,String.valueOf(i+1)),val);
-                }
+                matchStrings.add(val);
             }
-            vars.remove(concat(refName,String.valueOf(length+1)));
         } else if (objectType == XObject.CLASS_NULL
                 || objectType == XObject.CLASS_UNKNOWN
                 || objectType == XObject.CLASS_UNRESOLVEDVARIABLE) {
             log.warn("Unexpected object type: "+xObject.getTypeString()+" 
returned for: "+getXPathQuery());
-         } else {
+        } else {
             val = xObject.toString();
-            vars.put(concat(refName, MATCH_NR), "1");
-            vars.put(refName, val);
-            vars.put(concat(refName, "1"), val);
-            vars.remove(concat(refName, "2"));
-        }
+            matchStrings.add(val);
+      }
     }
 
     public void setWhitespace(boolean selected) {

Modified: 
jakarta/jmeter/trunk/src/components/org/apache/jmeter/extractor/gui/RegexExtractorGui.java
URL: 
http://svn.apache.org/viewvc/jakarta/jmeter/trunk/src/components/org/apache/jmeter/extractor/gui/RegexExtractorGui.java?rev=905149&r1=905148&r2=905149&view=diff
==============================================================================
--- 
jakarta/jmeter/trunk/src/components/org/apache/jmeter/extractor/gui/RegexExtractorGui.java
 (original)
+++ 
jakarta/jmeter/trunk/src/components/org/apache/jmeter/extractor/gui/RegexExtractorGui.java
 Mon Feb  1 00:17:15 2010
@@ -32,6 +32,7 @@
 
 import org.apache.jmeter.extractor.RegexExtractor;
 import org.apache.jmeter.processor.gui.AbstractPostProcessorGui;
+import org.apache.jmeter.testelement.AbstractScopedTestElement;
 import org.apache.jmeter.testelement.TestElement;
 import org.apache.jmeter.util.JMeterUtils;
 import org.apache.jorphan.gui.JLabeledTextField;
@@ -99,7 +100,7 @@
      * @see org.apache.jmeter.gui.JMeterGUIComponent#createTestElement()
      */
     public TestElement createTestElement() {
-        RegexExtractor extractor = new RegexExtractor();
+        AbstractScopedTestElement extractor = new RegexExtractor();
         modifyTestElement(extractor);
         return extractor;
     }

Modified: 
jakarta/jmeter/trunk/src/components/org/apache/jmeter/extractor/gui/XPathExtractorGui.java
URL: 
http://svn.apache.org/viewvc/jakarta/jmeter/trunk/src/components/org/apache/jmeter/extractor/gui/XPathExtractorGui.java?rev=905149&r1=905148&r2=905149&view=diff
==============================================================================
--- 
jakarta/jmeter/trunk/src/components/org/apache/jmeter/extractor/gui/XPathExtractorGui.java
 (original)
+++ 
jakarta/jmeter/trunk/src/components/org/apache/jmeter/extractor/gui/XPathExtractorGui.java
 Mon Feb  1 00:17:15 2010
@@ -44,16 +44,21 @@
 
     private static final long serialVersionUID = 240L;
 
-    private JLabeledTextField defaultField;
+    private final JLabeledTextField defaultField = 
+        new 
JLabeledTextField(JMeterUtils.getResString("default_value_field"));//$NON-NLS-1$
 
-    private JLabeledTextField xpathQueryField;
+    private final JLabeledTextField xpathQueryField = 
+        new 
JLabeledTextField(JMeterUtils.getResString("xpath_extractor_query"));//$NON-NLS-1$
 
-    private JLabeledTextField refNameField;
+    private final JLabeledTextField refNameField = 
+        new 
JLabeledTextField(JMeterUtils.getResString("ref_name_field"));//$NON-NLS-1$
 
-    private JCheckBox getFragment; // Should we return fragment as text, 
rather than text of fragment?
-    
-    private XMLConfPanel xml;
+    // Should we return fragment as text, rather than text of fragment?
+    private final JCheckBox getFragment = 
+        new 
JCheckBox(JMeterUtils.getResString("xpath_extractor_fragment"));//$NON-NLS-1$
     
+    private final XMLConfPanel xml = new XMLConfPanel();
+
     public String getLabelResource() {
         return "xpath_extractor_title"; //$NON-NLS-1$
     }
@@ -67,6 +72,7 @@
     public void configure(TestElement el) {
         super.configure(el);
         XPathExtractor xpe = (XPathExtractor) el;
+        showScopeSettings(xpe);
         xpathQueryField.setText(xpe.getXPathQuery());
         defaultField.setText(xpe.getDefaultValue());
         refNameField.setText(xpe.getRefName());
@@ -85,6 +91,7 @@
         super.configureTestElement(extractor);
         if ( extractor instanceof XPathExtractor){
             XPathExtractor xpath = (XPathExtractor)extractor;
+            saveScopeSettings(xpath);
             xpath.setDefaultValue(defaultField.getText());
             xpath.setRefName(refNameField.getText());
             xpath.setXPathQuery(xpathQueryField.getText());
@@ -112,11 +119,10 @@
 
         Box box = Box.createVerticalBox();
         box.add(makeTitlePanel());
-        xml = new XMLConfPanel();
+        box.add(createScopePanel());
         
xml.setBorder(BorderFactory.createTitledBorder(BorderFactory.createEtchedBorder(),
 JMeterUtils
                 .getResString("xpath_assertion_option"))); //$NON-NLS-1$
         box.add(xml);
-        getFragment = new 
JCheckBox(JMeterUtils.getResString("xpath_extractor_fragment"));//$NON-NLS-1$
         box.add(getFragment);
         box.add(makeParameterPanel());
         add(box, BorderLayout.NORTH);
@@ -124,10 +130,6 @@
 
 
     private JPanel makeParameterPanel() {
-        xpathQueryField = new 
JLabeledTextField(JMeterUtils.getResString("xpath_extractor_query"));//$NON-NLS-1$
-        defaultField = new 
JLabeledTextField(JMeterUtils.getResString("default_value_field"));//$NON-NLS-1$
-        refNameField = new 
JLabeledTextField(JMeterUtils.getResString("ref_name_field"));//$NON-NLS-1$
-
         JPanel panel = new JPanel(new GridBagLayout());
         GridBagConstraints gbc = new GridBagConstraints();
         initConstraints(gbc);

Modified: 
jakarta/jmeter/trunk/src/core/org/apache/jmeter/testelement/AbstractScopedTestElement.java
URL: 
http://svn.apache.org/viewvc/jakarta/jmeter/trunk/src/core/org/apache/jmeter/testelement/AbstractScopedTestElement.java?rev=905149&r1=905148&r2=905149&view=diff
==============================================================================
--- 
jakarta/jmeter/trunk/src/core/org/apache/jmeter/testelement/AbstractScopedTestElement.java
 (original)
+++ 
jakarta/jmeter/trunk/src/core/org/apache/jmeter/testelement/AbstractScopedTestElement.java
 Mon Feb  1 00:17:15 2010
@@ -18,6 +18,11 @@
 
 package org.apache.jmeter.testelement;
 
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.jmeter.samplers.SampleResult;
+
 /**
  * <p>
  * Super-class for TestElements that can be applied to main sample, 
sub-samples or both.
@@ -94,4 +99,26 @@
     public void setScopeAll() {
         setProperty(SCOPE, SCOPE_ALL);
     }
+
+    /**
+     * Generate a list of qualifying sample results,
+     * depending on the scope.
+     * 
+     * @param result current sample
+     * @return list containing the current sample and/or its child samples
+     */
+    protected List<SampleResult> getSampleList(SampleResult result) {
+        List<SampleResult> sampleList = new ArrayList<SampleResult>();
+    
+        String scope = fetchScope();
+        if (isScopeParent(scope) || isScopeAll(scope)) {
+            sampleList.add(result);
+        }
+        if (isScopeChildren(scope) || isScopeAll(scope)) {
+            for (SampleResult subResult : result.getSubResults()) {
+                sampleList.add(subResult);
+            }
+        }
+        return sampleList;
+    }
 }

Modified: 
jakarta/jmeter/trunk/test/src/org/apache/jmeter/extractor/TestXPathExtractor.java
URL: 
http://svn.apache.org/viewvc/jakarta/jmeter/trunk/test/src/org/apache/jmeter/extractor/TestXPathExtractor.java?rev=905149&r1=905148&r2=905149&view=diff
==============================================================================
--- 
jakarta/jmeter/trunk/test/src/org/apache/jmeter/extractor/TestXPathExtractor.java
 (original)
+++ 
jakarta/jmeter/trunk/test/src/org/apache/jmeter/extractor/TestXPathExtractor.java
 Mon Feb  1 00:17:15 2010
@@ -19,6 +19,8 @@
 package org.apache.jmeter.extractor;
 
 
+import java.io.UnsupportedEncodingException;
+
 import junit.framework.TestCase;
 
 import org.apache.jmeter.samplers.SampleResult;
@@ -31,6 +33,8 @@
 
         private SampleResult result;
 
+        private String data;
+        
         private JMeterVariables vars;
 
         public TestXPathExtractor(String name) {
@@ -42,15 +46,15 @@
         private final static String VAL_NAME = "value";
         private final static String VAL_NAME_NR = "value_matchNr";
         @Override
-        public void setUp() {
+        public void setUp() throws UnsupportedEncodingException {
             jmctx = JMeterContextService.getContext();
             extractor = new XPathExtractor();
             extractor.setThreadContext(jmctx);// This would be done by the run 
command
             extractor.setRefName(VAL_NAME);
             extractor.setDefaultValue("Default");
             result = new SampleResult();
-            String data = "<book><preface 
title='Intro'>zero</preface><page>one</page><page>two</page><empty></empty><a><b></b></a></book>";
-            result.setResponseData(data.getBytes());
+            data = "<book><preface 
title='Intro'>zero</preface><page>one</page><page>two</page><empty></empty><a><b></b></a></book>";
+            result.setResponseData(data.getBytes("UTF-8"));
             vars = new JMeterVariables();
             jmctx.setVariables(vars);
             jmctx.setPreviousResult(result);
@@ -150,6 +154,56 @@
             assertEquals("<a><b/></a>", vars.get(VAL_NAME));
         }
 
+        public void testScope(){
+            extractor.setXPathQuery("/book/preface");
+            extractor.process();
+            assertEquals("zero", vars.get(VAL_NAME));
+            assertEquals("1", vars.get(VAL_NAME_NR));
+            assertEquals("zero", vars.get(VAL_NAME+"_1"));
+            assertNull(vars.get(VAL_NAME+"_2"));            
+
+            extractor.setScopeChildren(); // There aren't any
+            extractor.process();
+            assertEquals("Default", vars.get(VAL_NAME));
+            assertEquals("0", vars.get(VAL_NAME_NR));
+            assertNull(vars.get(VAL_NAME+"_1"));
+
+            extractor.setScopeAll(); // same as Parent
+            extractor.process();
+            assertEquals("zero", vars.get(VAL_NAME));
+            assertEquals("1", vars.get(VAL_NAME_NR));
+            assertEquals("zero", vars.get(VAL_NAME+"_1"));
+            assertNull(vars.get(VAL_NAME+"_2"));            
+
+            // Try to get data from subresult
+            result.sampleStart(); // Needed for addSubResult()
+            result.sampleEnd();
+            SampleResult subResult = new SampleResult();
+            subResult.sampleStart();
+            subResult.setResponseData(result.getResponseData());
+            subResult.sampleEnd();
+            result.addSubResult(subResult);
+            
+            
+            // Get data from both
+            extractor.setScopeAll();
+            extractor.process();
+            assertEquals("zero", vars.get(VAL_NAME));
+            assertEquals("2", vars.get(VAL_NAME_NR));
+            assertEquals("zero", vars.get(VAL_NAME+"_1"));
+            assertEquals("zero", vars.get(VAL_NAME+"_2"));
+            assertNull(vars.get(VAL_NAME+"_3"));
+
+            // get data from child
+            extractor.setScopeChildren();
+            extractor.process();
+            assertEquals("zero", vars.get(VAL_NAME));
+            assertEquals("1", vars.get(VAL_NAME_NR));
+            assertEquals("zero", vars.get(VAL_NAME+"_1"));
+            assertNull(vars.get(VAL_NAME+"_2"));
+            
+        }
+
         public void testInvalidXpath() throws Exception {
             extractor.setXPathQuery("<");
             extractor.process();

Modified: jakarta/jmeter/trunk/xdocs/changes.xml
URL: 
http://svn.apache.org/viewvc/jakarta/jmeter/trunk/xdocs/changes.xml?rev=905149&r1=905148&r2=905149&view=diff
==============================================================================
--- jakarta/jmeter/trunk/xdocs/changes.xml (original)
+++ jakarta/jmeter/trunk/xdocs/changes.xml Mon Feb  1 00:17:15 2010
@@ -178,7 +178,8 @@
 <li>Added JSR223 Assertion</li>
 <li>Added BSF Timer and JSR223 Timer</li>
 <li>Bug 48331 - XpathExtractor does not return XML string representations for 
a Nodeset</li>
-<li>Bug 48511 - add parent,child,all selection to regex extractor panel</li>
+<li>Bug 48511 - add parent,child,all selection to regex extractor</li>
+<li>Add Sampler scope selection to XPathExtractor</li>
 </ul>
 
 <h3>Functions</h3>

Modified: jakarta/jmeter/trunk/xdocs/images/screenshots/xpath_extractor.png
URL: 
http://svn.apache.org/viewvc/jakarta/jmeter/trunk/xdocs/images/screenshots/xpath_extractor.png?rev=905149&r1=905148&r2=905149&view=diff
==============================================================================
Binary files - no diff available.

Modified: jakarta/jmeter/trunk/xdocs/usermanual/component_reference.xml
URL: 
http://svn.apache.org/viewvc/jakarta/jmeter/trunk/xdocs/usermanual/component_reference.xml?rev=905149&r1=905148&r2=905149&view=diff
==============================================================================
--- jakarta/jmeter/trunk/xdocs/usermanual/component_reference.xml (original)
+++ jakarta/jmeter/trunk/xdocs/usermanual/component_reference.xml Mon Feb  1 
00:17:15 2010
@@ -4108,13 +4108,23 @@
 </p>
 </component>
 
-<component name="XPath Extractor" index="&sect-num;.8.2"  width="613" 
height="269" screenshot="xpath_extractor.png">
-       <description>This test element allows the user to extract value from 
+<component name="XPath Extractor" index="&sect-num;.8.2"  width="612" 
height="318" screenshot="xpath_extractor.png">
+       <description>This test element allows the user to extract value(s) from 
                structured response - XML or (X)HTML - using XPath
                query language.
    </description>
    <properties>
-        <property name="Name" required="No">Descriptive name for this element 
that is shown in the tree.</property>
+       <property name="Name" required="No">Descriptive name for this element 
that is shown in the tree.</property>
+       <property name="Which samples to process" required="Yes">
+        This is for use with samplers that can generate sub-samples, 
+        e.g. HTTP Sampler with embedded resources, Mail Reader or samples 
generated by the Transaction Controller.
+        <ul>
+        <li>Main sample only - only applies to the main sample</li>
+        <li>Sub-samples only - only applies to the sub-samples</li>
+        <li>Main sample and sub-samples - applies to both.</li>
+        </ul>
+        XPath matching is applied to all qualifying samples in turn, and all 
the matching results will be returned.
+       </property>
           <property name="Use Tidy (tolerant parser)" required="Yes">If 
checked use Tidy to parse HTML response into XHTML.
           <ul>
                   <li>"Use Tidy" should be checked on for HTML response. Such 
response is converted to valid XHTML (XML compatible HTML) using Tidy</li>



---------------------------------------------------------------------
To unsubscribe, e-mail: jmeter-dev-unsubscr...@jakarta.apache.org
For additional commands, e-mail: jmeter-dev-h...@jakarta.apache.org

Reply via email to