You are viewing a plain text version of this content. The canonical link for it is here.
Posted to jmeter-dev@jakarta.apache.org by se...@apache.org on 2006/04/01 12:22:09 UTC
svn commit: r390640 - in /jakarta/jmeter/branches/rel-2-1:
src/components/org/apache/jmeter/extractor/XPathExtractor.java
test/src/org/apache/jmeter/extractor/TestXPathExtractor.java
xdocs/changes.xml xdocs/usermanual/component_reference.xml
Author: sebb
Date: Sat Apr 1 02:22:07 2006
New Revision: 390640
URL: http://svn.apache.org/viewcvs?rev=390640&view=rev
Log:
Add multiple node XPath extraction
Added:
jakarta/jmeter/branches/rel-2-1/test/src/org/apache/jmeter/extractor/TestXPathExtractor.java (with props)
Modified:
jakarta/jmeter/branches/rel-2-1/src/components/org/apache/jmeter/extractor/XPathExtractor.java
jakarta/jmeter/branches/rel-2-1/xdocs/changes.xml
jakarta/jmeter/branches/rel-2-1/xdocs/usermanual/component_reference.xml
Modified: jakarta/jmeter/branches/rel-2-1/src/components/org/apache/jmeter/extractor/XPathExtractor.java
URL: http://svn.apache.org/viewcvs/jakarta/jmeter/branches/rel-2-1/src/components/org/apache/jmeter/extractor/XPathExtractor.java?rev=390640&r1=390639&r2=390640&view=diff
==============================================================================
--- jakarta/jmeter/branches/rel-2-1/src/components/org/apache/jmeter/extractor/XPathExtractor.java (original)
+++ jakarta/jmeter/branches/rel-2-1/src/components/org/apache/jmeter/extractor/XPathExtractor.java Sat Apr 1 02:22:07 2006
@@ -37,8 +37,11 @@
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;
+//@see org.apache.jmeter.extractor.TestXPathExtractor for unit tests
+
/**
* Extracts text from (X)HTML response using XPath query language
* Example XPath queries:
@@ -59,7 +62,8 @@
*/
public class XPathExtractor extends AbstractTestElement implements
PostProcessor, Serializable {
- transient private static Logger log = LoggingManager.getLoggerForClass();
+ private static final String MATCH_NR = "matchNr";
+ transient private static Logger log = LoggingManager.getLoggerForClass();
protected static final String KEY_PREFIX = "XPathExtractor.";
public static final String XPATH_QUERY = KEY_PREFIX +"xpathQuery";
public static final String REFNAME = KEY_PREFIX +"refname";
@@ -67,6 +71,10 @@
public static final String TOLERANT = KEY_PREFIX +"tolerant";
+ private String concat(String s1,String s2){
+ return new StringBuffer(s1).append("_").append(s2).toString();
+ }
+
/**
* Do the job - extract value from (X)HTML response using XPath Query.
* Return value as variable defined by REFNAME. Returns DEFAULT value
@@ -77,25 +85,22 @@
JMeterVariables vars = context.getVariables();
String refName = getRefName();
vars.put(refName, getDefaultValue());
+ vars.put(concat(refName,MATCH_NR), "0"); // In case parse fails
+ vars.remove(concat(refName,"1")); // In case parse fails
try{
Document d = parseResponse(context.getPreviousResult());
- String val = getValueForXPath(d,getXPathQuery());
- if ( val!=null){
- vars.put(getRefName(),val);
- }
- }catch(IOException e){
+ getValuesForXPath(d,getXPathQuery(),vars, refName);
+ }catch(IOException e){// Should not happen
log.error("error on "+XPATH_QUERY+"("+getXPathQuery()+")",e);
throw new RuntimeException(e);
- } catch (ParserConfigurationException e) {
- log.error("error on "+XPATH_QUERY+"("+getXPathQuery()+")",e);
- throw new RuntimeException(e);
- } catch (SAXException e) {
- log.error("error on "+XPATH_QUERY+"("+getXPathQuery()+")",e);
- throw new RuntimeException(e);
- } catch (TransformerException e) {
+ } catch (ParserConfigurationException e) {// Should not happen
log.error("error on "+XPATH_QUERY+"("+getXPathQuery()+")",e);
throw new RuntimeException(e);
+ } catch (SAXException e) {// Can happen for bad input document
+ log.warn("error on "+XPATH_QUERY+"("+getXPathQuery()+")"+e.getLocalizedMessage());
+ } catch (TransformerException e) {// Can happen for incorrect XPath expression
+ log.warn("error on "+XPATH_QUERY+"("+getXPathQuery()+")"+e.getLocalizedMessage());
}
}
@@ -173,12 +178,15 @@
* data were not found
* @throws TransformerException
*/
- private String getValueForXPath(Document d,String query)
+ private void getValuesForXPath(Document d,String query, JMeterVariables vars, String refName)
throws TransformerException
{
- String val = null;
- Node match = XPathAPI.selectSingleNode(d,query);
- if ( match!=null){
+ String val = null;
+ NodeList matches = XPathAPI.selectNodeList(d,query);
+ 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){
// elements have empty nodeValue, but we are usually
// interested in their content
@@ -186,11 +194,14 @@
} 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);
+ }
}
- if ( log.isDebugEnabled()){
- log.debug(XPATH_QUERY+"("+query+") is '"+val+"'");
- }
- return val;
+ vars.remove(concat(refName,String.valueOf(length+1)));
}
}
Added: jakarta/jmeter/branches/rel-2-1/test/src/org/apache/jmeter/extractor/TestXPathExtractor.java
URL: http://svn.apache.org/viewcvs/jakarta/jmeter/branches/rel-2-1/test/src/org/apache/jmeter/extractor/TestXPathExtractor.java?rev=390640&view=auto
==============================================================================
--- jakarta/jmeter/branches/rel-2-1/test/src/org/apache/jmeter/extractor/TestXPathExtractor.java (added)
+++ jakarta/jmeter/branches/rel-2-1/test/src/org/apache/jmeter/extractor/TestXPathExtractor.java Sat Apr 1 02:22:07 2006
@@ -0,0 +1,106 @@
+/*
+ * Copyright 2003-2005 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.apache.jmeter.extractor;
+
+
+import junit.framework.TestCase;
+
+import org.apache.jmeter.samplers.SampleResult;
+import org.apache.jmeter.threads.JMeterContext;
+import org.apache.jmeter.threads.JMeterContextService;
+import org.apache.jmeter.threads.JMeterVariables;
+
+/**
+ * @version $Revision$
+ */
+public class TestXPathExtractor extends TestCase {
+ XPathExtractor extractor;
+
+ SampleResult result;
+
+ JMeterVariables vars;
+
+ public TestXPathExtractor(String name) {
+ super(name);
+ }
+
+ private JMeterContext jmctx = null;
+
+ private final static String VAL_NAME = "value";
+ private final static String VAL_NAME_NR = "value_matchNr";
+ public void setUp() {
+ 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>zero</preface><page>one</page><page>two</page></book>";
+ result.setResponseData(data.getBytes());
+ vars = new JMeterVariables();
+ jmctx.setVariables(vars);
+ jmctx.setPreviousResult(result);
+ }
+
+ public void testVariableExtraction() throws Exception {
+ 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.setXPathQuery("/book/page");
+ extractor.process();
+ assertEquals("one", vars.get(VAL_NAME));
+ assertEquals("2", vars.get(VAL_NAME_NR));
+ assertEquals("one", vars.get(VAL_NAME+"_1"));
+ assertEquals("two", vars.get(VAL_NAME+"_2"));
+ assertNull(vars.get(VAL_NAME+"_3"));
+
+ extractor.setXPathQuery("/book/page[2]");
+ extractor.process();
+ assertEquals("two", vars.get(VAL_NAME));
+ assertEquals("1", vars.get(VAL_NAME_NR));
+ assertEquals("two", vars.get(VAL_NAME+"_1"));
+ assertNull(vars.get(VAL_NAME+"_2"));
+ assertNull(vars.get(VAL_NAME+"_3"));
+
+ extractor.setXPathQuery("/book/index");
+ extractor.process();
+ assertEquals("Default", vars.get(VAL_NAME));
+ assertEquals("0", vars.get(VAL_NAME_NR));
+ assertNull(vars.get(VAL_NAME+"_1"));
+
+ }
+
+ public void testInvalidXpath() throws Exception {
+ extractor.setXPathQuery("<");
+ extractor.process();
+ assertEquals("Default", vars.get(VAL_NAME));
+ assertEquals("0", vars.get(VAL_NAME_NR));
+ }
+
+ public void testInvalidDocument() throws Exception {
+ result.setResponseData("<z>".getBytes());
+ extractor.setXPathQuery("<");
+ extractor.process();
+ assertEquals("Default", vars.get(VAL_NAME));
+ assertEquals("0", vars.get(VAL_NAME_NR));
+ }
+}
Propchange: jakarta/jmeter/branches/rel-2-1/test/src/org/apache/jmeter/extractor/TestXPathExtractor.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: jakarta/jmeter/branches/rel-2-1/test/src/org/apache/jmeter/extractor/TestXPathExtractor.java
------------------------------------------------------------------------------
svn:keywords = Date Author Id Revision
Propchange: jakarta/jmeter/branches/rel-2-1/test/src/org/apache/jmeter/extractor/TestXPathExtractor.java
------------------------------------------------------------------------------
svn:mime-type = text/plain
Modified: jakarta/jmeter/branches/rel-2-1/xdocs/changes.xml
URL: http://svn.apache.org/viewcvs/jakarta/jmeter/branches/rel-2-1/xdocs/changes.xml?rev=390640&r1=390639&r2=390640&view=diff
==============================================================================
--- jakarta/jmeter/branches/rel-2-1/xdocs/changes.xml (original)
+++ jakarta/jmeter/branches/rel-2-1/xdocs/changes.xml Sat Apr 1 02:22:07 2006
@@ -48,7 +48,7 @@
<h4>New functionality:</h4>
<ul>
<li>Report function</li>
-<li>XPath Extractor</li>
+<li>XPath Extractor Post-Processor. Handles single and multiple matches.</li>
<li>Simpler JMX file format (2.2)</li>
<li>BeanshellSampler code can update ResponseData directly</li>
<li>Bug 37490 - Allow UDV as delay in Duration Assertion</li>
Modified: jakarta/jmeter/branches/rel-2-1/xdocs/usermanual/component_reference.xml
URL: http://svn.apache.org/viewcvs/jakarta/jmeter/branches/rel-2-1/xdocs/usermanual/component_reference.xml?rev=390640&r1=390639&r2=390640&view=diff
==============================================================================
--- jakarta/jmeter/branches/rel-2-1/xdocs/usermanual/component_reference.xml (original)
+++ jakarta/jmeter/branches/rel-2-1/xdocs/usermanual/component_reference.xml Sat Apr 1 02:22:07 2006
@@ -2699,15 +2699,29 @@
</property>
<property name="Name" required="">Descriptive name for this element that is shown in the tree.</property>
<property name="Reference Name" required="Yes">The name of the JMeter variable in which to store the result.</property>
- <property name="XPath Query" required="Yes">Element query in XPath language. </property>
+ <property name="XPath Query" required="Yes">Element query in XPath language. Can return more than one match. </property>
<property name="Default Value" required="">Default value returned when no match found</property>
</properties>
+ <p>To allow for use in a ForEach Controller, the following variables are set on return:</p>
+ <ul>
+ <li>refName - set to first (or only) match; if no match, then set to default</li>
+ <li>refName_matchNr - set to number of matches (may be 0)</li>
+ <li>refName_n - n=1,2,3 etc. Set to the 1st, 2nd 3rd match etc.
+ </li>
+ </ul>
+ <p>Note: The next refName_n variable is set to null - e.g. if there are 2 matches, then refName_3 is set to null,
+ and if there are no matches, then refName_1 is set to null.
+ </p>
<p>XPath is query language targeted primarily for XSLT transformations. However it is usefull as generic query language for structured data too. See
<a href="http://www.topxml.com/xsl/xpathref.asp">XPath Reference</a> or <a href="http://www.w3.org/TR/xpath">XPath specification</a> for more information. Here are few examples:
</p>
<dl>
<dt>/html/head/title</dt>
<dd>extracts title element from HTML response</dd>
+ <dt>/book/page[2]</dt>
+ <dd>extracts 2nd page from a book</dd>
+ <dt>/book/page</dt>
+ <dd>extracts all pages from a book</dd>
<dt>//form[@name='countryForm']//select[@name='country']/option[text()='Czech Republic'])/@value</dt>
<dd>extracts value attribute of option element that match text 'Czech Republic'
inside of select element with name attribute 'country' inside of
---------------------------------------------------------------------
To unsubscribe, e-mail: jmeter-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: jmeter-dev-help@jakarta.apache.org