jmeter-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From pmoua...@apache.org
Subject svn commit: r1832784 [1/2] - in /jmeter/trunk: ./ bin/ lib/ licenses/bin/ res/maven/ src/components/org/apache/jmeter/extractor/ src/components/org/apache/jmeter/extractor/gui/ src/components/org/apache/jmeter/visualizers/ src/core/org/apache/jmeter/re...
Date Sun, 03 Jun 2018 19:05:09 GMT
Author: pmouawad
Date: Sun Jun  3 19:05:08 2018
New Revision: 1832784

URL: http://svn.apache.org/viewvc?rev=1832784&view=rev
Log:
Bug 60991 - XPath Extractor : Implement XPath 2.0

Contributed by UbikLoadPack
Bugzilla Id: 60991

Added:
    jmeter/trunk/licenses/bin/Saxon-HE-9.8.0-12.txt   (with props)
    jmeter/trunk/src/components/org/apache/jmeter/extractor/XPath2Extractor.java   (with props)
    jmeter/trunk/src/components/org/apache/jmeter/extractor/gui/XPath2ExtractorGui.java   (with props)
    jmeter/trunk/src/components/org/apache/jmeter/visualizers/RenderAsXPath2.java   (with props)
    jmeter/trunk/src/core/org/apache/jmeter/util/XPathQueryCacheLoader.java   (with props)
    jmeter/trunk/test/resources/XPathUtilTestXml.xml   (with props)
    jmeter/trunk/xdocs/images/screenshots/xpath2_extractor.png   (with props)
Modified:
    jmeter/trunk/LICENSE
    jmeter/trunk/bin/jmeter.properties
    jmeter/trunk/bin/saveservice.properties
    jmeter/trunk/build.properties
    jmeter/trunk/build.xml
    jmeter/trunk/eclipse.classpath
    jmeter/trunk/lib/   (props changed)
    jmeter/trunk/lib/aareadme.txt
    jmeter/trunk/res/maven/ApacheJMeter_parent.pom
    jmeter/trunk/src/core/org/apache/jmeter/resources/messages.properties
    jmeter/trunk/src/core/org/apache/jmeter/resources/messages_fr.properties
    jmeter/trunk/src/core/org/apache/jmeter/util/XPathUtil.java
    jmeter/trunk/test/src/org/apache/jmeter/util/XPathUtilTest.java
    jmeter/trunk/xdocs/changes.xml
    jmeter/trunk/xdocs/usermanual/component_reference.xml
    jmeter/trunk/xdocs/usermanual/properties_reference.xml

Modified: jmeter/trunk/LICENSE
URL: http://svn.apache.org/viewvc/jmeter/trunk/LICENSE?rev=1832784&r1=1832783&r2=1832784&view=diff
==============================================================================
--- jmeter/trunk/LICENSE [utf-8] (original)
+++ jmeter/trunk/LICENSE [utf-8] Sun Jun  3 19:05:08 2018
@@ -284,3 +284,4 @@ For details, please see the files under:
 * xpp3-1.1.4c.jar (Indiana University Extreme! Lab Software License 1.1.1)
 * xstream-1.4.10.jar (BSD)
 * hamcrest-date-2.0.4.jar (BSD)
+* Saxon-HE-9.8.0-12.jar (Mozilla Public License version 2.0)
\ No newline at end of file

Modified: jmeter/trunk/bin/jmeter.properties
URL: http://svn.apache.org/viewvc/jmeter/trunk/bin/jmeter.properties?rev=1832784&r1=1832783&r2=1832784&view=diff
==============================================================================
--- jmeter/trunk/bin/jmeter.properties (original)
+++ jmeter/trunk/bin/jmeter.properties Sun Jun  3 19:05:08 2018
@@ -54,6 +54,10 @@
 # ns=http://biz.aol.com/schema/2006-12-18
 #xpath.namespace.config=
 
+
+# XPath2 query cache for storing compiled XPath queries
+#xpath2query.parser.cache.size=400
+
 #---------------------------------------------------------------------------
 # SSL configuration
 #---------------------------------------------------------------------------

Modified: jmeter/trunk/bin/saveservice.properties
URL: http://svn.apache.org/viewvc/jmeter/trunk/bin/saveservice.properties?rev=1832784&r1=1832783&r2=1832784&view=diff
==============================================================================
--- jmeter/trunk/bin/saveservice.properties (original)
+++ jmeter/trunk/bin/saveservice.properties Sun Jun  3 19:05:08 2018
@@ -64,8 +64,9 @@
 # 2.9 = 2.14
 # 3.1 = 3.1
 # 3.2 = 3.2
-# 3.4 = 3.4
-_version=4.0
+# 4.0 = 4.0
+# 4.1 = 4.1
+_version=4.1
 #
 #
 # Character set encoding used to read and write JMeter XML files and CSV results
@@ -364,7 +365,9 @@ XPathAssertion=org.apache.jmeter.asserti
 XPathAssertionGui=org.apache.jmeter.assertions.gui.XPathAssertionGui
 XPathExtractor=org.apache.jmeter.extractor.XPathExtractor
 XPathExtractorGui=org.apache.jmeter.extractor.gui.XPathExtractorGui
-#
+XPath2Extractor=org.apache.jmeter.extractor.XPath2Extractor
+XPath2ExtractorGui=org.apache.jmeter.extractor.gui.XPath2ExtractorGui
+
 # Properties - all start with lower case letter and end with Prop
 #
 boolProp=org.apache.jmeter.testelement.property.BooleanProperty

Modified: jmeter/trunk/build.properties
URL: http://svn.apache.org/viewvc/jmeter/trunk/build.properties?rev=1832784&r1=1832783&r2=1832784&view=diff
==============================================================================
--- jmeter/trunk/build.properties (original)
+++ jmeter/trunk/build.properties Sun Jun  3 19:05:08 2018
@@ -473,6 +473,12 @@ activemq-all.jar             = activemq-
 activemq-all.loc             = ${maven2.repo}/org/apache/activemq/activemq-all/${activemq-all.version}
 activemq-all.md5             = bd24ae082be11dc969a6e5bc45515ab7
 
+# Used by XPath 2
+saxon-HE.version              = 9.8.0-12
+saxon-HE.jar                  = Saxon-HE-${saxon-HE.version}.jar
+saxon-HE.loc                 = ${maven2.repo}/net/sf/saxon/Saxon-HE/${saxon-HE.version}
+saxon-HE.md5                  = 80e040add296c6545b92d7cb1b648534
+
 # Optional for use by FTP_TESTS.jmx
 mina-core.version            = 2.0.16
 mina-core.jar                = mina-core-${mina-core.version}.jar

Modified: jmeter/trunk/build.xml
URL: http://svn.apache.org/viewvc/jmeter/trunk/build.xml?rev=1832784&r1=1832783&r2=1832784&view=diff
==============================================================================
--- jmeter/trunk/build.xml (original)
+++ jmeter/trunk/build.xml Sun Jun  3 19:05:08 2018
@@ -446,6 +446,7 @@
     <include name="${lib.dir}/${tika-core.jar}"/>
     <include name="${lib.dir}/${tika-parsers.jar}"/>
     <include name="${lib.dir}/${xalan.jar}"/>
+    <include name="${lib.dir}/${saxon-HE.jar}"/>
     <include name="${lib.dir}/${xerces.jar}"/>
     <include name="${lib.dir}/${xml-apis.jar}"/>
     <include name="${lib.dir}/${xmlgraphics-commons.jar}"/>
@@ -532,6 +533,7 @@
     <pathelement location="${lib.dir}/${tika-core.jar}"/>
     <pathelement location="${lib.dir}/${tika-parsers.jar}"/>
     <pathelement location="${lib.dir}/${xalan.jar}"/>
+    <pathelement location="${lib.dir}/${saxon-HE.jar}"/>
     <pathelement location="${lib.dir}/${xerces.jar}"/>
     <pathelement location="${lib.dir}/${xml-apis.jar}"/>
     <pathelement location="${lib.dir}/${xmlgraphics-commons.jar}"/>
@@ -3400,6 +3402,7 @@ run JMeter unless all the JMeter jars ar
     <process_jarfile jarname="velocity"   dest.dir="${lib.doc}"/>
     <process_jarfile jarname="commons-lang" dest.dir="${lib.doc}"/>
     <process_jarfile jarname="xalan"/>
+    <process_jarfile jarname="saxon-HE"/>
     <process_jarfile jarname="xerces"/>
     <process_jarfile jarname="xml-apis"/>
     <process_jarfile jarname="xmlgraphics-commons"/>

Modified: jmeter/trunk/eclipse.classpath
URL: http://svn.apache.org/viewvc/jmeter/trunk/eclipse.classpath?rev=1832784&r1=1832783&r2=1832784&view=diff
==============================================================================
--- jmeter/trunk/eclipse.classpath (original)
+++ jmeter/trunk/eclipse.classpath Sun Jun  3 19:05:08 2018
@@ -97,6 +97,7 @@
 	<classpathentry kind="lib" path="lib/ph-commons-9.0.0.jar"/>
 	<classpathentry kind="lib" path="lib/rhino-1.7.7.2.jar"/>
 	<classpathentry kind="lib" path="lib/rsyntaxtextarea-2.6.1.jar"/>
+	<classpathentry kind="lib" path="lib/Saxon-HE-9.8.0-12.jar"/>
 	<classpathentry kind="lib" path="lib/serializer-2.7.2.jar"/>
 	<classpathentry kind="lib" path="lib/slf4j-api-1.7.25.jar"/>
 	<classpathentry kind="lib" path="lib/slf4j-ext-1.7.25.jar"/>

Propchange: jmeter/trunk/lib/
------------------------------------------------------------------------------
--- svn:ignore (original)
+++ svn:ignore Sun Jun  3 19:05:08 2018
@@ -60,6 +60,7 @@ rsyntaxtextarea-2.6.1.jar
 objenesis-2.6.jar
 oro-2.0.8.jar
 rhino-1.7.7.2.jar
+Saxon-HE-9.8.0-12.jar
 serializer-2.7.2.jar
 slf4j-api-1.7.25.jar
 slf4j-ext-1.7.25.jar

Modified: jmeter/trunk/lib/aareadme.txt
URL: http://svn.apache.org/viewvc/jmeter/trunk/lib/aareadme.txt?rev=1832784&r1=1832783&r2=1832784&view=diff
==============================================================================
--- jmeter/trunk/lib/aareadme.txt (original)
+++ jmeter/trunk/lib/aareadme.txt Sun Jun  3 19:05:08 2018
@@ -249,6 +249,10 @@ commons-dbcp2-2.2.0 (org.apache.commons.
 --------------------------
 - DataSourceElement (JDBC)
 
+Saxon-HE-9.8.0-12 (net.sf.saxon)
+--------------------------
+- XPath2Extractor (XML)
+
 velocity-1.7
 --------------
 http://velocity.apache.org/download.cgi

Added: jmeter/trunk/licenses/bin/Saxon-HE-9.8.0-12.txt
URL: http://svn.apache.org/viewvc/jmeter/trunk/licenses/bin/Saxon-HE-9.8.0-12.txt?rev=1832784&view=auto
==============================================================================
--- jmeter/trunk/licenses/bin/Saxon-HE-9.8.0-12.txt (added)
+++ jmeter/trunk/licenses/bin/Saxon-HE-9.8.0-12.txt Sun Jun  3 19:05:08 2018
@@ -0,0 +1,373 @@
+Mozilla Public License Version 2.0
+==================================
+
+1. Definitions
+--------------
+
+1.1. "Contributor"
+    means each individual or legal entity that creates, contributes to
+    the creation of, or owns Covered Software.
+
+1.2. "Contributor Version"
+    means the combination of the Contributions of others (if any) used
+    by a Contributor and that particular Contributor's Contribution.
+
+1.3. "Contribution"
+    means Covered Software of a particular Contributor.
+
+1.4. "Covered Software"
+    means Source Code Form to which the initial Contributor has attached
+    the notice in Exhibit A, the Executable Form of such Source Code
+    Form, and Modifications of such Source Code Form, in each case
+    including portions thereof.
+
+1.5. "Incompatible With Secondary Licenses"
+    means
+
+    (a) that the initial Contributor has attached the notice described
+        in Exhibit B to the Covered Software; or
+
+    (b) that the Covered Software was made available under the terms of
+        version 1.1 or earlier of the License, but not also under the
+        terms of a Secondary License.
+
+1.6. "Executable Form"
+    means any form of the work other than Source Code Form.
+
+1.7. "Larger Work"
+    means a work that combines Covered Software with other material, in 
+    a separate file or files, that is not Covered Software.
+
+1.8. "License"
+    means this document.
+
+1.9. "Licensable"
+    means having the right to grant, to the maximum extent possible,
+    whether at the time of the initial grant or subsequently, any and
+    all of the rights conveyed by this License.
+
+1.10. "Modifications"
+    means any of the following:
+
+    (a) any file in Source Code Form that results from an addition to,
+        deletion from, or modification of the contents of Covered
+        Software; or
+
+    (b) any new file in Source Code Form that contains any Covered
+        Software.
+
+1.11. "Patent Claims" of a Contributor
+    means any patent claim(s), including without limitation, method,
+    process, and apparatus claims, in any patent Licensable by such
+    Contributor that would be infringed, but for the grant of the
+    License, by the making, using, selling, offering for sale, having
+    made, import, or transfer of either its Contributions or its
+    Contributor Version.
+
+1.12. "Secondary License"
+    means either the GNU General Public License, Version 2.0, the GNU
+    Lesser General Public License, Version 2.1, the GNU Affero General
+    Public License, Version 3.0, or any later versions of those
+    licenses.
+
+1.13. "Source Code Form"
+    means the form of the work preferred for making modifications.
+
+1.14. "You" (or "Your")
+    means an individual or a legal entity exercising rights under this
+    License. For legal entities, "You" includes any entity that
+    controls, is controlled by, or is under common control with You. For
+    purposes of this definition, "control" means (a) the power, direct
+    or indirect, to cause the direction or management of such entity,
+    whether by contract or otherwise, or (b) ownership of more than
+    fifty percent (50%) of the outstanding shares or beneficial
+    ownership of such entity.
+
+2. License Grants and Conditions
+--------------------------------
+
+2.1. Grants
+
+Each Contributor hereby grants You a world-wide, royalty-free,
+non-exclusive license:
+
+(a) under intellectual property rights (other than patent or trademark)
+    Licensable by such Contributor to use, reproduce, make available,
+    modify, display, perform, distribute, and otherwise exploit its
+    Contributions, either on an unmodified basis, with Modifications, or
+    as part of a Larger Work; and
+
+(b) under Patent Claims of such Contributor to make, use, sell, offer
+    for sale, have made, import, and otherwise transfer either its
+    Contributions or its Contributor Version.
+
+2.2. Effective Date
+
+The licenses granted in Section 2.1 with respect to any Contribution
+become effective for each Contribution on the date the Contributor first
+distributes such Contribution.
+
+2.3. Limitations on Grant Scope
+
+The licenses granted in this Section 2 are the only rights granted under
+this License. No additional rights or licenses will be implied from the
+distribution or licensing of Covered Software under this License.
+Notwithstanding Section 2.1(b) above, no patent license is granted by a
+Contributor:
+
+(a) for any code that a Contributor has removed from Covered Software;
+    or
+
+(b) for infringements caused by: (i) Your and any other third party's
+    modifications of Covered Software, or (ii) the combination of its
+    Contributions with other software (except as part of its Contributor
+    Version); or
+
+(c) under Patent Claims infringed by Covered Software in the absence of
+    its Contributions.
+
+This License does not grant any rights in the trademarks, service marks,
+or logos of any Contributor (except as may be necessary to comply with
+the notice requirements in Section 3.4).
+
+2.4. Subsequent Licenses
+
+No Contributor makes additional grants as a result of Your choice to
+distribute the Covered Software under a subsequent version of this
+License (see Section 10.2) or under the terms of a Secondary License (if
+permitted under the terms of Section 3.3).
+
+2.5. Representation
+
+Each Contributor represents that the Contributor believes its
+Contributions are its original creation(s) or it has sufficient rights
+to grant the rights to its Contributions conveyed by this License.
+
+2.6. Fair Use
+
+This License is not intended to limit any rights You have under
+applicable copyright doctrines of fair use, fair dealing, or other
+equivalents.
+
+2.7. Conditions
+
+Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted
+in Section 2.1.
+
+3. Responsibilities
+-------------------
+
+3.1. Distribution of Source Form
+
+All distribution of Covered Software in Source Code Form, including any
+Modifications that You create or to which You contribute, must be under
+the terms of this License. You must inform recipients that the Source
+Code Form of the Covered Software is governed by the terms of this
+License, and how they can obtain a copy of this License. You may not
+attempt to alter or restrict the recipients' rights in the Source Code
+Form.
+
+3.2. Distribution of Executable Form
+
+If You distribute Covered Software in Executable Form then:
+
+(a) such Covered Software must also be made available in Source Code
+    Form, as described in Section 3.1, and You must inform recipients of
+    the Executable Form how they can obtain a copy of such Source Code
+    Form by reasonable means in a timely manner, at a charge no more
+    than the cost of distribution to the recipient; and
+
+(b) You may distribute such Executable Form under the terms of this
+    License, or sublicense it under different terms, provided that the
+    license for the Executable Form does not attempt to limit or alter
+    the recipients' rights in the Source Code Form under this License.
+
+3.3. Distribution of a Larger Work
+
+You may create and distribute a Larger Work under terms of Your choice,
+provided that You also comply with the requirements of this License for
+the Covered Software. If the Larger Work is a combination of Covered
+Software with a work governed by one or more Secondary Licenses, and the
+Covered Software is not Incompatible With Secondary Licenses, this
+License permits You to additionally distribute such Covered Software
+under the terms of such Secondary License(s), so that the recipient of
+the Larger Work may, at their option, further distribute the Covered
+Software under the terms of either this License or such Secondary
+License(s).
+
+3.4. Notices
+
+You may not remove or alter the substance of any license notices
+(including copyright notices, patent notices, disclaimers of warranty,
+or limitations of liability) contained within the Source Code Form of
+the Covered Software, except that You may alter any license notices to
+the extent required to remedy known factual inaccuracies.
+
+3.5. Application of Additional Terms
+
+You may choose to offer, and to charge a fee for, warranty, support,
+indemnity or liability obligations to one or more recipients of Covered
+Software. However, You may do so only on Your own behalf, and not on
+behalf of any Contributor. You must make it absolutely clear that any
+such warranty, support, indemnity, or liability obligation is offered by
+You alone, and You hereby agree to indemnify every Contributor for any
+liability incurred by such Contributor as a result of warranty, support,
+indemnity or liability terms You offer. You may include additional
+disclaimers of warranty and limitations of liability specific to any
+jurisdiction.
+
+4. Inability to Comply Due to Statute or Regulation
+---------------------------------------------------
+
+If it is impossible for You to comply with any of the terms of this
+License with respect to some or all of the Covered Software due to
+statute, judicial order, or regulation then You must: (a) comply with
+the terms of this License to the maximum extent possible; and (b)
+describe the limitations and the code they affect. Such description must
+be placed in a text file included with all distributions of the Covered
+Software under this License. Except to the extent prohibited by statute
+or regulation, such description must be sufficiently detailed for a
+recipient of ordinary skill to be able to understand it.
+
+5. Termination
+--------------
+
+5.1. The rights granted under this License will terminate automatically
+if You fail to comply with any of its terms. However, if You become
+compliant, then the rights granted under this License from a particular
+Contributor are reinstated (a) provisionally, unless and until such
+Contributor explicitly and finally terminates Your grants, and (b) on an
+ongoing basis, if such Contributor fails to notify You of the
+non-compliance by some reasonable means prior to 60 days after You have
+come back into compliance. Moreover, Your grants from a particular
+Contributor are reinstated on an ongoing basis if such Contributor
+notifies You of the non-compliance by some reasonable means, this is the
+first time You have received notice of non-compliance with this License
+from such Contributor, and You become compliant prior to 30 days after
+Your receipt of the notice.
+
+5.2. If You initiate litigation against any entity by asserting a patent
+infringement claim (excluding declaratory judgment actions,
+counter-claims, and cross-claims) alleging that a Contributor Version
+directly or indirectly infringes any patent, then the rights granted to
+You by any and all Contributors for the Covered Software under Section
+2.1 of this License shall terminate.
+
+5.3. In the event of termination under Sections 5.1 or 5.2 above, all
+end user license agreements (excluding distributors and resellers) which
+have been validly granted by You or Your distributors under this License
+prior to termination shall survive termination.
+
+************************************************************************
+*                                                                      *
+*  6. Disclaimer of Warranty                                           *
+*  -------------------------                                           *
+*                                                                      *
+*  Covered Software is provided under this License on an "as is"       *
+*  basis, without warranty of any kind, either expressed, implied, or  *
+*  statutory, including, without limitation, warranties that the       *
+*  Covered Software is free of defects, merchantable, fit for a        *
+*  particular purpose or non-infringing. The entire risk as to the     *
+*  quality and performance of the Covered Software is with You.        *
+*  Should any Covered Software prove defective in any respect, You     *
+*  (not any Contributor) assume the cost of any necessary servicing,   *
+*  repair, or correction. This disclaimer of warranty constitutes an   *
+*  essential part of this License. No use of any Covered Software is   *
+*  authorized under this License except under this disclaimer.         *
+*                                                                      *
+************************************************************************
+
+************************************************************************
+*                                                                      *
+*  7. Limitation of Liability                                          *
+*  --------------------------                                          *
+*                                                                      *
+*  Under no circumstances and under no legal theory, whether tort      *
+*  (including negligence), contract, or otherwise, shall any           *
+*  Contributor, or anyone who distributes Covered Software as          *
+*  permitted above, be liable to You for any direct, indirect,         *
+*  special, incidental, or consequential damages of any character      *
+*  including, without limitation, damages for lost profits, loss of    *
+*  goodwill, work stoppage, computer failure or malfunction, or any    *
+*  and all other commercial damages or losses, even if such party      *
+*  shall have been informed of the possibility of such damages. This   *
+*  limitation of liability shall not apply to liability for death or   *
+*  personal injury resulting from such party's negligence to the       *
+*  extent applicable law prohibits such limitation. Some               *
+*  jurisdictions do not allow the exclusion or limitation of           *
+*  incidental or consequential damages, so this exclusion and          *
+*  limitation may not apply to You.                                    *
+*                                                                      *
+************************************************************************
+
+8. Litigation
+-------------
+
+Any litigation relating to this License may be brought only in the
+courts of a jurisdiction where the defendant maintains its principal
+place of business and such litigation shall be governed by laws of that
+jurisdiction, without reference to its conflict-of-law provisions.
+Nothing in this Section shall prevent a party's ability to bring
+cross-claims or counter-claims.
+
+9. Miscellaneous
+----------------
+
+This License represents the complete agreement concerning the subject
+matter hereof. If any provision of this License is held to be
+unenforceable, such provision shall be reformed only to the extent
+necessary to make it enforceable. Any law or regulation which provides
+that the language of a contract shall be construed against the drafter
+shall not be used to construe this License against a Contributor.
+
+10. Versions of the License
+---------------------------
+
+10.1. New Versions
+
+Mozilla Foundation is the license steward. Except as provided in Section
+10.3, no one other than the license steward has the right to modify or
+publish new versions of this License. Each version will be given a
+distinguishing version number.
+
+10.2. Effect of New Versions
+
+You may distribute the Covered Software under the terms of the version
+of the License under which You originally received the Covered Software,
+or under the terms of any subsequent version published by the license
+steward.
+
+10.3. Modified Versions
+
+If you create software not governed by this License, and you want to
+create a new license for such software, you may create and use a
+modified version of this License if you rename the license and remove
+any references to the name of the license steward (except to note that
+such modified license differs from this License).
+
+10.4. Distributing Source Code Form that is Incompatible With Secondary
+Licenses
+
+If You choose to distribute Source Code Form that is Incompatible With
+Secondary Licenses under the terms of this version of the License, the
+notice described in Exhibit B of this License must be attached.
+
+Exhibit A - Source Code Form License Notice
+-------------------------------------------
+
+  This Source Code Form is subject to the terms of the Mozilla Public
+  License, v. 2.0. If a copy of the MPL was not distributed with this
+  file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+If it is not possible or desirable to put the notice in a particular
+file, then You may include the notice in a location (such as a LICENSE
+file in a relevant directory) where a recipient would be likely to look
+for such a notice.
+
+You may add additional accurate notices of copyright ownership.
+
+Exhibit B - "Incompatible With Secondary Licenses" Notice
+---------------------------------------------------------
+
+  This Source Code Form is "Incompatible With Secondary Licenses", as
+  defined by the Mozilla Public License, v. 2.0.

Propchange: jmeter/trunk/licenses/bin/Saxon-HE-9.8.0-12.txt
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: jmeter/trunk/licenses/bin/Saxon-HE-9.8.0-12.txt
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Modified: jmeter/trunk/res/maven/ApacheJMeter_parent.pom
URL: http://svn.apache.org/viewvc/jmeter/trunk/res/maven/ApacheJMeter_parent.pom?rev=1832784&r1=1832783&r2=1832784&view=diff
==============================================================================
--- jmeter/trunk/res/maven/ApacheJMeter_parent.pom (original)
+++ jmeter/trunk/res/maven/ApacheJMeter_parent.pom Sun Jun  3 19:05:08 2018
@@ -99,6 +99,7 @@ under the License.
       <ph-css.version>6.0.0</ph-css.version>
       <ph-commons.version>9.0.0</ph-commons.version>
       <rsyntaxtextarea.version>2.6.1</rsyntaxtextarea.version>
+      <saxon-HE.version>9.8.0-12</saxon-HE.version>
       <slf4j-api.version>1.7.25</slf4j-api.version>
       <slf4j-ext.version>1.7.25</slf4j-ext.version>
       <log4j-api.version>2.10.0</log4j-api.version>
@@ -333,6 +334,11 @@ under the License.
         <version>${serializer.version}</version>
       </dependency>
       <dependency>
+        <groupId>net.sf.saxon</groupId>
+        <artifactId>Saxon-HE</artifactId>
+        <version>${saxon-HE.version}</version>
+      </dependency>
+      <dependency>
         <groupId>xerces</groupId>
         <artifactId>xercesImpl</artifactId>
         <version>${xerces.version}</version>

Added: jmeter/trunk/src/components/org/apache/jmeter/extractor/XPath2Extractor.java
URL: http://svn.apache.org/viewvc/jmeter/trunk/src/components/org/apache/jmeter/extractor/XPath2Extractor.java?rev=1832784&view=auto
==============================================================================
--- jmeter/trunk/src/components/org/apache/jmeter/extractor/XPath2Extractor.java (added)
+++ jmeter/trunk/src/components/org/apache/jmeter/extractor/XPath2Extractor.java Sun Jun  3 19:05:08 2018
@@ -0,0 +1,278 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 java.io.Serializable;
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.xml.stream.FactoryConfigurationError;
+import javax.xml.stream.XMLStreamException;
+
+import org.apache.jmeter.assertions.AssertionResult;
+import org.apache.jmeter.processor.PostProcessor;
+import org.apache.jmeter.samplers.SampleResult;
+import org.apache.jmeter.testelement.AbstractScopedTestElement;
+import org.apache.jmeter.testelement.property.IntegerProperty;
+import org.apache.jmeter.threads.JMeterContext;
+import org.apache.jmeter.threads.JMeterVariables;
+import org.apache.jmeter.util.XPathUtil;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import net.sf.saxon.s9api.SaxonApiException;
+
+/**
+ * Extracts text from (X)HTML response using XPath query language
+ * Example XPath queries:
+ * <dl>
+ * <dt>/html/head/title</dt>
+ *     <dd>extracts Title from HTML response</dd>
+ * <dt>//form[@name='countryForm']//select[@name='country']/option[text()='Czech Republic'])/@value
+ *     <dd>extracts value attribute of option element that match text 'Czech Republic'
+ *                 inside of select element with name attribute  'country' inside of
+ *                 form with name attribute 'countryForm'</dd>
+ * <dt>//head</dt>
+ *     <dd>extracts the XML fragment for head node.</dd>
+ * <dt>//head/text()</dt>
+ *     <dd>extracts the text content for head node.</dd>
+ * </dl>
+  see org.apache.jmeter.extractor.TestXPathExtractor for unit tests
+ */
+public class XPath2Extractor extends AbstractScopedTestElement implements
+PostProcessor, Serializable {
+    private static final Logger log = LoggerFactory.getLogger(XPathExtractor.class);
+
+    private static final long serialVersionUID = 242L;
+
+    private static final int DEFAULT_VALUE = 0;
+    public static final String DEFAULT_VALUE_AS_STRING = Integer.toString(DEFAULT_VALUE);
+
+    private static final String REF_MATCH_NR    = "matchNr"; // $NON-NLS-1$
+
+    //+ JMX file attributes
+    private static final String XPATH_QUERY     = "XPathExtractor2.xpathQuery"; // $NON-NLS-1$
+    private static final String REFNAME         = "XPathExtractor2.refname"; // $NON-NLS-1$
+    private static final String DEFAULT         = "XPathExtractor2.default"; // $NON-NLS-1$
+    private static final String FRAGMENT        = "XPathExtractor2.fragment"; // $NON-NLS-1$
+    private static final String NAMESPACES      = "XPathExtractor2.namespaces"; // $NON-NLS-1$
+    private static final String MATCH_NUMBER    = "XPathExtractor2.matchNumber"; // $NON-NLS-1$
+    //- JMX file attributes
+
+    private String concat(String s1,String s2){
+        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
+     * if not found.
+     */
+    @Override
+    public void process() {
+        JMeterContext context = getThreadContext();
+        final SampleResult previousResult = context.getPreviousResult();
+        if (previousResult == null){
+            return;
+        }
+        JMeterVariables vars = context.getVariables();
+        String refName = getRefName();
+        vars.put(refName, getDefaultValue());
+        final String matchNR = concat(refName,REF_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$
+
+        int matchNumber = getMatchNumber();
+        List<String> matches = new ArrayList<>();
+        try{
+            if (isScopeVariable()){
+                String inputString=vars.get(getVariableName());
+                if(inputString != null) {
+                    if(inputString.length()>0) {
+                        getValuesForXPath(getXPathQuery(), matches, matchNumber,previousResult.getResponseDataAsString());
+                    }
+                } else {
+                    if (log.isWarnEnabled()) {
+                        log.warn("No variable '{}' found to process by XPathExtractor '{}', skipping processing",
+                                getVariableName(), getName());
+                    }
+                }
+            } else {
+                List<SampleResult> samples = getSampleList(previousResult);
+                int size = samples.size();
+                for(int i = 0;i<size;i++) {
+                    getValuesForXPath(getXPathQuery(), matches, matchNumber,previousResult.getResponseDataAsString());
+                }
+            }
+            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 (Exception e) {// Saxon exception
+            if (log.isWarnEnabled()) {
+                log.warn("Exception while processing '{})', message:{}", getXPathQuery(), e.getMessage());
+            }
+            addAssertionFailure(previousResult, e, false);
+        }
+    }
+
+    private void addAssertionFailure(final SampleResult previousResult,
+            final Throwable thrown, final boolean setFailed) {
+        AssertionResult ass = new AssertionResult(getName()); // $NON-NLS-1$
+        ass.setFailure(true);
+        ass.setFailureMessage(thrown.getLocalizedMessage()+"\nSee log file for further details.");
+        previousResult.addAssertionResult(ass);
+        if (setFailed){
+            previousResult.setSuccessful(false);
+        }
+    }
+
+    /*============= object properties ================*/
+    public void setXPathQuery(String val){
+        setProperty(XPATH_QUERY,val);
+    }
+
+    public String getXPathQuery(){
+        return getPropertyAsString(XPATH_QUERY);
+    }
+
+    public void setRefName(String refName) {
+        setProperty(REFNAME, refName);
+    }
+
+    public String getRefName() {
+        return getPropertyAsString(REFNAME);
+    }
+
+
+    public void setDefaultValue(String val) {
+        setProperty(DEFAULT, val);
+    }
+
+    public String getDefaultValue() {
+        return getPropertyAsString(DEFAULT);
+    }
+
+    /**
+     * Should we return fragment as text, rather than text of fragment?
+     * @return true if we should return fragment rather than text
+     */
+    public boolean getFragment() {
+        return getPropertyAsBoolean(FRAGMENT, false);
+    }
+
+    /**
+     * Should we return fragment as text, rather than text of fragment?
+     * @param selected true to return fragment.
+     */
+    public void setFragment(boolean selected) {
+        setProperty(FRAGMENT, selected, false);
+    }
+
+    /*================= internal business =================*/
+
+    /**
+     * Extract value from String responseData by XPath query.
+     * @param query the query to execute
+     * @param matchStrings list of matched strings (may include nulls)
+     * @param matchNumber int Match Number
+     * @param responseData String that contains the entire Document
+     * @throws SaxonApiException
+     * @throws XMLStreamException 
+     * @throws FactoryConfigurationError 
+     */
+    private void getValuesForXPath(String query, List<String> matchStrings, int matchNumber, String responseData)
+            throws SaxonApiException, XMLStreamException, FactoryConfigurationError {
+        XPathUtil.putValuesForXPathInListUsingSaxon(responseData, query, matchStrings, getFragment(), matchNumber, getNamespaces());
+    }
+
+    /**
+     * Set which Match to use. This can be any positive number, indicating the
+     * exact match to use, or <code>0</code>, which is interpreted as meaning random.
+     *
+     * @param matchNumber The number of the match to be used
+     */
+    public void setMatchNumber(int matchNumber) {
+        setProperty(new IntegerProperty(MATCH_NUMBER, matchNumber));
+    }
+
+    /**
+     * Set which Match to use. This can be any positive number, indicating the
+     * exact match to use, or <code>0</code>, which is interpreted as meaning random.
+     *
+     * @param matchNumber The number of the match to be used
+     */
+    public void setMatchNumber(String matchNumber) {
+        setProperty(MATCH_NUMBER, matchNumber);
+    }
+
+    /**
+     * Return which Match to use. This can be any positive number, indicating the
+     * exact match to use, or <code>0</code>, which is interpreted as meaning random.
+     *
+     * @return matchNumber The number of the match to be used
+     */
+    public int getMatchNumber() {
+        return getPropertyAsInt(MATCH_NUMBER, DEFAULT_VALUE);
+    }
+
+    /**
+     * Return which Match to use. This can be any positive number, indicating the
+     * exact match to use, or <code>0</code>, which is interpreted as meaning random.
+     *
+     * @return matchNumber The number of the match to be used
+     */
+    public String getMatchNumberAsString() {
+        return getPropertyAsString(MATCH_NUMBER, DEFAULT_VALUE_AS_STRING);
+    }
+
+    public void setNamespaces(String namespaces) {
+        setProperty(NAMESPACES, namespaces);
+    }
+
+    public String getNamespaces() {
+        return getPropertyAsString(NAMESPACES);
+    }
+}

Propchange: jmeter/trunk/src/components/org/apache/jmeter/extractor/XPath2Extractor.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: jmeter/trunk/src/components/org/apache/jmeter/extractor/XPath2Extractor.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: jmeter/trunk/src/components/org/apache/jmeter/extractor/gui/XPath2ExtractorGui.java
URL: http://svn.apache.org/viewvc/jmeter/trunk/src/components/org/apache/jmeter/extractor/gui/XPath2ExtractorGui.java?rev=1832784&view=auto
==============================================================================
--- jmeter/trunk/src/components/org/apache/jmeter/extractor/gui/XPath2ExtractorGui.java (added)
+++ jmeter/trunk/src/components/org/apache/jmeter/extractor/gui/XPath2ExtractorGui.java Sun Jun  3 19:05:08 2018
@@ -0,0 +1,183 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.gui;
+
+import java.awt.BorderLayout;
+import java.awt.GridBagConstraints;
+import java.awt.GridBagLayout;
+import java.util.List;
+
+import javax.swing.Box;
+import javax.swing.JCheckBox;
+import javax.swing.JComponent;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+
+import org.apache.jmeter.extractor.XPath2Extractor;
+import org.apache.jmeter.gui.util.JSyntaxTextArea;
+import org.apache.jmeter.gui.util.JTextScrollPane;
+import org.apache.jmeter.processor.gui.AbstractPostProcessorGui;
+import org.apache.jmeter.testelement.TestElement;
+import org.apache.jmeter.util.JMeterUtils;
+import org.apache.jorphan.gui.JLabeledTextField;
+
+/**
+ * GUI for XPath2Extractor class.
+ * @since 4.1
+ */
+public class XPath2ExtractorGui extends AbstractPostProcessorGui{ // NOSONAR Ignore parents warning
+
+    private static final long serialVersionUID = 1L;
+
+    private final JLabeledTextField defaultField = new JLabeledTextField(
+            JMeterUtils.getResString("default_value_field"));//$NON-NLS-1$
+
+    private final JLabeledTextField xpathQueryField = new JLabeledTextField(
+            JMeterUtils.getResString("xpath_extractor_query"));//$NON-NLS-1$
+
+    private final JLabeledTextField matchNumberField = new JLabeledTextField(
+            JMeterUtils.getResString("match_num_field"));//$NON-NLS-1$
+
+    private final JLabeledTextField refNameField = new JLabeledTextField(JMeterUtils.getResString("ref_name_field"));//$NON-NLS-1$
+
+    // Should we return fragment as text, rather than text of fragment?
+    private JCheckBox getFragment;
+    
+    private JSyntaxTextArea namespacesTA;
+    
+    @Override
+    public String getLabelResource() {
+        return "xpath2_extractor_title"; //$NON-NLS-1$
+    }
+
+    public XPath2ExtractorGui() {
+        super();
+        init();
+    }
+
+    @Override
+    public void configure(TestElement el) {
+        super.configure(el);
+        XPath2Extractor xpe = (XPath2Extractor) el;
+        showScopeSettings(xpe, true);
+        xpathQueryField.setText(xpe.getXPathQuery());
+        defaultField.setText(xpe.getDefaultValue());
+        refNameField.setText(xpe.getRefName());
+        matchNumberField.setText(xpe.getMatchNumberAsString());
+        namespacesTA.setText(xpe.getNamespaces());
+        getFragment.setSelected(xpe.getFragment());
+    }
+
+    @Override
+    public TestElement createTestElement() {
+        XPath2Extractor extractor = new XPath2Extractor();
+        modifyTestElement(extractor);
+        return extractor;
+    }
+
+    @Override
+    public void modifyTestElement(TestElement extractor) {
+        super.configureTestElement(extractor);
+        if (extractor instanceof XPath2Extractor) {
+            XPath2Extractor xpath = (XPath2Extractor) extractor;
+            saveScopeSettings(xpath);
+            xpath.setDefaultValue(defaultField.getText());
+            xpath.setRefName(refNameField.getText());
+            xpath.setMatchNumber(matchNumberField.getText());
+            xpath.setXPathQuery(xpathQueryField.getText());
+            xpath.setFragment(getFragment.isSelected());
+            xpath.setNamespaces(namespacesTA.getText());
+        }
+    }
+
+    /**
+     * Implements JMeterGUIComponent.clearGui
+     */
+    @Override
+    public void clearGui() {
+        super.clearGui();
+        xpathQueryField.setText(""); // $NON-NLS-1$
+        defaultField.setText(""); // $NON-NLS-1$
+        refNameField.setText(""); // $NON-NLS-1$
+        matchNumberField.setText(XPath2Extractor.DEFAULT_VALUE_AS_STRING); // $NON-NLS-1$
+        namespacesTA.setText("");
+    }
+
+    private void init() { // WARNING: called from ctor so must not be overridden (i.e. must be private or final)
+        setLayout(new BorderLayout());
+        setBorder(makeBorder());
+        Box box = Box.createVerticalBox();
+        box.add(makeTitlePanel());
+        box.add(createScopePanel(true, true, true));
+        box.add(makeParameterPanel());
+        add(box, BorderLayout.NORTH);
+    }
+    
+    private JPanel makeParameterPanel() {
+        JPanel panel = new JPanel(new GridBagLayout());
+        GridBagConstraints gbc = new GridBagConstraints();
+        initConstraints(gbc);
+        addField(panel, refNameField, gbc);
+        resetContraints(gbc);
+        addField(panel, xpathQueryField, gbc);
+        resetContraints(gbc);
+        addField(panel, matchNumberField, gbc);
+        resetContraints(gbc);
+        addField(panel, defaultField, gbc);
+        resetContraints(gbc);
+        panel.add(new JLabel(JMeterUtils.getResString("xpath_extractor_user_namespaces")), gbc.clone());
+        gbc.gridx++;
+        gbc.weightx = 1;
+        gbc.fill = GridBagConstraints.HORIZONTAL;
+        namespacesTA = JSyntaxTextArea.getInstance(5, 80);
+        panel.add(JTextScrollPane.getInstance(namespacesTA, true), gbc.clone());
+
+        resetContraints(gbc);
+        gbc.gridwidth = 2;
+        getFragment = new JCheckBox(JMeterUtils.getResString("xpath_extractor_fragment"));//$NON-NLS-1$
+        panel.add(getFragment, gbc.clone());
+        return panel;
+    }
+
+    private void addField(JPanel panel, JLabeledTextField field, GridBagConstraints gbc) {
+        List<JComponent> item = field.getComponentList();
+        panel.add(item.get(0), gbc.clone());
+        gbc.gridx++;
+        gbc.weightx = 1;
+        gbc.fill = GridBagConstraints.HORIZONTAL;
+        panel.add(item.get(1), gbc.clone());
+    }
+
+    private void resetContraints(GridBagConstraints gbc) {
+        gbc.gridx = 0;
+        gbc.gridy++;
+        gbc.weightx = 0;
+        gbc.fill = GridBagConstraints.NONE;
+    }
+
+    private void initConstraints(GridBagConstraints gbc) {
+        gbc.anchor = GridBagConstraints.NORTHWEST;
+        gbc.fill = GridBagConstraints.NONE;
+        gbc.gridheight = 1;
+        gbc.gridwidth = 1;
+        gbc.gridx = 0;
+        gbc.gridy = 0;
+        gbc.weightx = 0;
+        gbc.weighty = 0;
+    }
+}

Propchange: jmeter/trunk/src/components/org/apache/jmeter/extractor/gui/XPath2ExtractorGui.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: jmeter/trunk/src/components/org/apache/jmeter/extractor/gui/XPath2ExtractorGui.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: jmeter/trunk/src/components/org/apache/jmeter/visualizers/RenderAsXPath2.java
URL: http://svn.apache.org/viewvc/jmeter/trunk/src/components/org/apache/jmeter/visualizers/RenderAsXPath2.java?rev=1832784&view=auto
==============================================================================
--- jmeter/trunk/src/components/org/apache/jmeter/visualizers/RenderAsXPath2.java (added)
+++ jmeter/trunk/src/components/org/apache/jmeter/visualizers/RenderAsXPath2.java Sun Jun  3 19:05:08 2018
@@ -0,0 +1,293 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with this
+ * work for additional information regarding copyright ownership. The ASF
+ * licenses this file to You 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.visualizers;
+
+import java.awt.BorderLayout;
+import java.awt.Color;
+import java.awt.Dimension;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.swing.Box;
+import javax.swing.JButton;
+import javax.swing.JCheckBox;
+import javax.swing.JPanel;
+import javax.swing.JScrollPane;
+import javax.swing.JSplitPane;
+import javax.swing.JTabbedPane;
+import javax.swing.JTextArea;
+import javax.swing.border.Border;
+import javax.swing.border.EmptyBorder;
+
+import org.apache.commons.lang3.exception.ExceptionUtils;
+import org.apache.jmeter.extractor.XPath2Extractor;
+import org.apache.jmeter.gui.util.JSyntaxTextArea;
+import org.apache.jmeter.gui.util.JTextScrollPane;
+import org.apache.jmeter.samplers.SampleResult;
+import org.apache.jmeter.util.JMeterUtils;
+import org.apache.jmeter.util.XPathUtil;
+import org.apache.jorphan.gui.GuiUtils;
+import org.apache.jorphan.gui.JLabeledTextField;
+import org.fife.ui.rsyntaxtextarea.SyntaxConstants;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+
+/**
+ * Implement ResultsRender for XPath tester
+ */
+public class RenderAsXPath2 implements ResultRenderer, ActionListener {
+
+    private static final Logger log = LoggerFactory.getLogger(RenderAsXPath.class);
+
+    private static final String XPATH_TESTER_COMMAND = "xpath_tester"; // $NON-NLS-1$
+    
+    private static final String XPATH_NAMESPACES_COMMAND = "xpath_namespaces"; // $NON-NLS-1$
+
+    private JPanel xmlWithXPathPane;
+
+    private JSyntaxTextArea xmlDataField;
+
+    private JLabeledTextField xpathExpressionField;
+
+    private JTextArea xpathResultField;
+
+    private JTabbedPane rightSide;
+
+    private SampleResult sampleResult = null;
+    
+    // Should we return fragment as text, rather than text of fragment?
+    private final JCheckBox getFragment =
+        new JCheckBox(JMeterUtils.getResString("xpath_tester_fragment"));//$NON-NLS-1$
+    
+    /** {@inheritDoc} */
+    @Override
+    public void clearData() {
+        // N.B. don't set xpathExpressionField to empty to keep xpath
+        this.xmlDataField.setText(""); // $NON-NLS-1$
+        this.xpathResultField.setText(""); // $NON-NLS-1$
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public void init() {
+        // Create the panels for the xpath tab
+        xmlWithXPathPane = createXpathExtractorPanel();
+    }
+
+    /**
+     * Display the response as text or as rendered HTML. Change the text on the
+     * button appropriate to the current display.
+     *
+     * @param e the ActionEvent being processed
+     */
+    @Override
+    public void actionPerformed(ActionEvent e) {
+        String command = e.getActionCommand();
+        if ((sampleResult != null) && (XPATH_TESTER_COMMAND.equals(command))) {
+            String response = xmlDataField.getText();
+            XPath2Extractor extractor = new XPath2Extractor();
+            extractor.setFragment(getFragment.isSelected());
+            executeAndShowXPathTester(response, extractor);
+        }
+        else if ((sampleResult != null) && (XPATH_NAMESPACES_COMMAND.equals(command))) {
+            String response = xmlDataField.getText();
+            this.xpathResultField.setText(getDocumentNamespaces(response));
+        }
+    }
+
+    /**
+     * Launch xpath engine to parse a input text
+     * @param textToParse
+     */
+    private void executeAndShowXPathTester(String textToParse, XPath2Extractor extractor) {
+        if (textToParse != null && textToParse.length() > 0
+                && this.xpathExpressionField.getText().length() > 0) {
+            this.xpathResultField.setText(process(textToParse, extractor));
+            this.xpathResultField.setCaretPosition(0); // go to first line
+        }
+    }
+
+    private String process(String textToParse, XPath2Extractor extractor) {
+        try {
+            List<String> matchStrings = new ArrayList<>();
+            XPathUtil.putValuesForXPathInListUsingSaxon(textToParse, xpathExpressionField.getText(), matchStrings, extractor.getFragment(), -1, getDocumentNamespaces(textToParse));
+            StringBuilder builder = new StringBuilder();
+            int nbFound = matchStrings.size();
+            builder.append("Match count: ").append(nbFound).append("\n");
+            for (int i = 0; i < nbFound; i++) {
+                builder.append("Match[").append(i+1).append("]=").append(matchStrings.get(i)).append("\n");
+            }
+            return builder.toString();
+        } catch (Exception e) {
+            return "Exception:"+ ExceptionUtils.getStackTrace(e);
+        }
+    }
+    
+    
+    private String getDocumentNamespaces(String textToParse) {
+        StringBuilder result = new StringBuilder();
+        try {
+            List<String[]> namespaces = XPathUtil.getNamespaces(textToParse);
+            for (int i = 0;i<namespaces.size();i++) {
+                result.append(namespaces.get(i)[0])
+                .append('=') // $NON-NLS-1$
+                .append(namespaces.get(i)[1])
+                .append('\n'); // $NON-NLS-1$
+            }
+            return result.toString();
+        } catch (Exception e) {
+            return "Exception:"+ ExceptionUtils.getStackTrace(e);
+        }
+    }
+    
+    /*================= internal business =================*/
+    /** {@inheritDoc} */
+    @Override
+    public void renderResult(SampleResult sampleResult) {
+        String response = ViewResultsFullVisualizer.getResponseAsString(sampleResult);
+        try {
+            xmlDataField.setText(response == null ? "" : response);
+            xmlDataField.setCaretPosition(0);
+        } catch (Exception e) {
+            log.error("Exception converting to XML: {}, message: {}", response, e.getMessage(), e);
+            xmlDataField.setText("Exception converting to XML:"+response+ ", message:"+e.getMessage());
+            xmlDataField.setCaretPosition(0);
+        }
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public String toString() {
+        return JMeterUtils.getResString("xpath2_tester"); // $NON-NLS-1$
+    }
+
+
+    /** {@inheritDoc} */
+    @Override
+    public void setupTabPane() {
+         // Add xpath tester pane
+        if (rightSide.indexOfTab(JMeterUtils.getResString("xpath_tester_title")) < 0) { // $NON-NLS-1$
+            rightSide.addTab(JMeterUtils.getResString("xpath_tester_title"), xmlWithXPathPane); // $NON-NLS-1$
+        }
+        clearData();
+    }
+
+    /**
+     * @return XPath Tester panel
+     */
+    private JPanel createXpathExtractorPanel() {
+        xmlDataField = JSyntaxTextArea.getInstance(50, 80, true);
+        xmlDataField.setCodeFoldingEnabled(true);
+        xmlDataField.setEditable(false);
+        xmlDataField.setBracketMatchingEnabled(false);
+        xmlDataField.setSyntaxEditingStyle(SyntaxConstants.SYNTAX_STYLE_XML);
+        xmlDataField.setLanguage(SyntaxConstants.SYNTAX_STYLE_XML);
+        xmlDataField.setLineWrap(true);
+        xmlDataField.setWrapStyleWord(true);
+
+        JScrollPane xmlDataPane = JTextScrollPane.getInstance(xmlDataField, true);
+        xmlDataPane.setPreferredSize(new Dimension(0, 200));
+
+        JPanel pane = new JPanel(new BorderLayout(0, 5));
+
+        JSplitPane mainSplit = new JSplitPane(JSplitPane.VERTICAL_SPLIT,
+                xmlDataPane, createXpathExtractorTasksPanel());
+        mainSplit.setDividerLocation(0.6d);
+        mainSplit.setOneTouchExpandable(true);
+        pane.add(mainSplit, BorderLayout.CENTER);
+        return pane;
+    }
+
+    /**
+     * Create the XPath task pane
+     *
+     * @return XPath task pane
+     */
+    private JPanel createXpathExtractorTasksPanel() {
+        Box xpathActionPanel = Box.createVerticalBox();
+        
+        Box selectorAndButton = Box.createHorizontalBox();
+
+        Border margin = new EmptyBorder(5, 5, 0, 5);
+        xpathActionPanel.setBorder(margin);
+        xpathExpressionField = new JLabeledTextField(JMeterUtils.getResString("xpath_tester_field")); // $NON-NLS-1$
+        
+        JButton xpathTester = new JButton(JMeterUtils.getResString("xpath_tester_button_test")); // $NON-NLS-1$
+        xpathTester.setActionCommand(XPATH_TESTER_COMMAND);
+        xpathTester.addActionListener(this);
+        
+        JButton xpathTesterNamespaces = new JButton(JMeterUtils.getResString("xpath_namespaces")); // $NON-NLS-1$
+        xpathTesterNamespaces.setActionCommand(XPATH_NAMESPACES_COMMAND);
+        xpathTesterNamespaces.addActionListener(this);
+        
+        selectorAndButton.add(xpathExpressionField);
+        selectorAndButton.add(xpathTester);
+        selectorAndButton.add(xpathTesterNamespaces);
+        
+        xpathActionPanel.add(selectorAndButton);
+        xpathActionPanel.add(getFragment);
+        
+        xpathResultField = new JTextArea();
+        xpathResultField.setEditable(false);
+        xpathResultField.setLineWrap(true);
+        xpathResultField.setWrapStyleWord(true);
+
+        JPanel xpathTasksPanel = new JPanel(new BorderLayout(0, 5));
+        xpathTasksPanel.add(xpathActionPanel, BorderLayout.NORTH);
+        xpathTasksPanel.add(GuiUtils.makeScrollPane(xpathResultField), BorderLayout.CENTER);
+
+        return xpathTasksPanel;
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public synchronized void setRightSide(JTabbedPane side) {
+        rightSide = side;
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public synchronized void setSamplerResult(Object userObject) {
+        if (userObject instanceof SampleResult) {
+            sampleResult = (SampleResult) userObject;
+        }
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public void setLastSelectedTab(int index) {
+        // nothing to do
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public void renderImage(SampleResult sampleResult) {
+        clearData();
+        xmlDataField.setText(JMeterUtils.getResString("xpath_tester_no_text")); // $NON-NLS-1$
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public void setBackgroundColor(Color backGround) {
+        // NOOP
+    }
+}

Propchange: jmeter/trunk/src/components/org/apache/jmeter/visualizers/RenderAsXPath2.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: jmeter/trunk/src/components/org/apache/jmeter/visualizers/RenderAsXPath2.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Modified: jmeter/trunk/src/core/org/apache/jmeter/resources/messages.properties
URL: http://svn.apache.org/viewvc/jmeter/trunk/src/core/org/apache/jmeter/resources/messages.properties?rev=1832784&r1=1832783&r2=1832784&view=diff
==============================================================================
--- jmeter/trunk/src/core/org/apache/jmeter/resources/messages.properties (original)
+++ jmeter/trunk/src/core/org/apache/jmeter/resources/messages.properties Sun Jun  3 19:05:08 2018
@@ -1396,6 +1396,7 @@ web_testing_source_ip_device_ipv4=Device
 web_testing_source_ip_device_ipv6=Device IPv6
 web_testing_source_ip_hostname=IP/Hostname
 web_testing_title=HTTP Request
+web_testing_namespaces=Namespaces (prefix = value)
 while_controller_label=Condition (function or variable)
 while_controller_title=While Controller
 workbench_title=WorkBench
@@ -1423,9 +1424,12 @@ xpath_assertion_whitespace=Ignore whites
 xpath_expression=XPath expression to match against
 xpath_extractor_fragment=Return entire XPath fragment instead of text content?
 xpath_extractor_query=XPath query:
+xpath_extractor_user_namespaces=Namespaces list :
 xpath_extractor_title=XPath Extractor
 xpath_file_file_name=XML file to get values from 
 xpath_tester=XPath Tester
+xpath2_tester=XPath2 Tester
+xpath_namespaces=Show namespaces aliases
 xpath_tester_button_test=Test
 xpath_tester_field=XPath expression
 xpath_tester_fragment=Return entire XPath fragment instead of text content?
@@ -1434,6 +1438,9 @@ xpath_tester_title=XPath Tester
 xpath_tidy_quiet=Quiet
 xpath_tidy_report_errors=Report errors
 xpath_tidy_show_warnings=Show warnings
+xpath2_extractor_title=XPath2 Extractor
+xpath2_extractor_empty_query=Empty XPath expression !
+xpath2_extractor_match_number_failure=MatchNumber out of bonds \:
 you_must_enter_a_valid_number=You must enter a valid number
 zh_cn=Chinese (Simplified)
 zh_tw=Chinese (Traditional)

Modified: jmeter/trunk/src/core/org/apache/jmeter/resources/messages_fr.properties
URL: http://svn.apache.org/viewvc/jmeter/trunk/src/core/org/apache/jmeter/resources/messages_fr.properties?rev=1832784&r1=1832783&r2=1832784&view=diff
==============================================================================
--- jmeter/trunk/src/core/org/apache/jmeter/resources/messages_fr.properties (original)
+++ jmeter/trunk/src/core/org/apache/jmeter/resources/messages_fr.properties Sun Jun  3 19:05:08 2018
@@ -1385,6 +1385,7 @@ web_testing_source_ip_device_ipv4=Interf
 web_testing_source_ip_device_ipv6=Interface IPv6
 web_testing_source_ip_hostname=IP/Nom d'h\u00F4te
 web_testing_title=Requ\u00EAte HTTP
+web_testing_namespaces=Namespaces (prefix = value)
 while_controller_label=Condition (fonction ou variable) \:
 while_controller_title=Contr\u00F4leur Tant Que
 workbench_title=Plan de travail
@@ -1412,9 +1413,12 @@ xpath_assertion_whitespace=Ignorer les e
 xpath_expression=Expression XPath de correspondance
 xpath_extractor_fragment=Retourner le fragment XPath entier au lieu du contenu
 xpath_extractor_query=Requ\u00EAte XPath \:
+xpath_extractor_user_namespaces=Liste des namespaces :
 xpath_extractor_title=Extracteur XPath
 xpath_file_file_name=Fichier XML contenant les valeurs
 xpath_tester=Testeur XPath
+xpath2_tester=Testeur XPath2
+xpath_namespaces=Voir alias namespaces
 xpath_tester_button_test=Tester
 xpath_tester_field=Expression XPath
 xpath_tester_fragment=Retourner le fragment XPath entier au lieu du contenu ?
@@ -1423,6 +1427,9 @@ xpath_tester_title=Testeur XPath
 xpath_tidy_quiet=Silencieux
 xpath_tidy_report_errors=Rapporter les erreurs
 xpath_tidy_show_warnings=Afficher les alertes
+xpath2_extractor_title=Extracteur XPath2
+xpath2_extractor_empty_query=Expression XPath vide !
+xpath2_extractor_match_number_failure=Correspondance hors de port\u00E9e : 
 you_must_enter_a_valid_number=Vous devez entrer un nombre valide
 zh_cn=Chinois (simplifi\u00E9)
 zh_tw=Chinois (traditionnel)

Added: jmeter/trunk/src/core/org/apache/jmeter/util/XPathQueryCacheLoader.java
URL: http://svn.apache.org/viewvc/jmeter/trunk/src/core/org/apache/jmeter/util/XPathQueryCacheLoader.java?rev=1832784&view=auto
==============================================================================
--- jmeter/trunk/src/core/org/apache/jmeter/util/XPathQueryCacheLoader.java (added)
+++ jmeter/trunk/src/core/org/apache/jmeter/util/XPathQueryCacheLoader.java Sun Jun  3 19:05:08 2018
@@ -0,0 +1,60 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.util;
+
+import java.util.List;
+
+import org.apache.commons.lang3.tuple.ImmutablePair;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.github.benmanes.caffeine.cache.CacheLoader;
+
+import net.sf.saxon.s9api.Processor;
+import net.sf.saxon.s9api.XPathCompiler;
+import net.sf.saxon.s9api.XPathExecutable;
+
+/**
+ * load method is called when the key composed of
+ * namespaces + xPathQuery is not in the cache.
+ * Return the compiled XPathQuery with the associated
+ * namespaces.
+ */
+public class XPathQueryCacheLoader implements CacheLoader<ImmutablePair<String, String>, XPathExecutable> {
+    
+    private static final Logger log = LoggerFactory.getLogger(XPathQueryCacheLoader.class);
+
+    @Override
+    public XPathExecutable load(ImmutablePair<String, String> key) 
+            throws Exception {
+        String xPathQuery = key.left;
+        String namespacesString = key.right;
+
+        Processor processor = XPathUtil.getProcessor();
+        XPathCompiler xPathCompiler = processor.newXPathCompiler();
+
+        List<String[]> namespacesList = XPathUtil.namespacesParse(namespacesString);
+        log.debug("Parsed namespaces:{} into list of namespaces:{}", namespacesString, namespacesList);
+        for (String[] namespaces : namespacesList) {
+            xPathCompiler.declareNamespace(namespaces[0], namespaces[1]);
+        }
+        log.debug("Declared namespaces:{}, now compiling xPathQuery:{}", namespacesList, xPathQuery);
+        return xPathCompiler.compile(xPathQuery);
+    }
+}

Propchange: jmeter/trunk/src/core/org/apache/jmeter/util/XPathQueryCacheLoader.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: jmeter/trunk/src/core/org/apache/jmeter/util/XPathQueryCacheLoader.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Modified: jmeter/trunk/src/core/org/apache/jmeter/util/XPathUtil.java
URL: http://svn.apache.org/viewvc/jmeter/trunk/src/core/org/apache/jmeter/util/XPathUtil.java?rev=1832784&r1=1832783&r2=1832784&view=diff
==============================================================================
--- jmeter/trunk/src/core/org/apache/jmeter/util/XPathUtil.java (original)
+++ jmeter/trunk/src/core/org/apache/jmeter/util/XPathUtil.java Sun Jun  3 19:05:08 2018
@@ -26,11 +26,17 @@ import java.io.PrintWriter;
 import java.io.StringReader;
 import java.io.StringWriter;
 import java.nio.charset.StandardCharsets;
+import java.util.ArrayList;
 import java.util.List;
 
 import javax.xml.parsers.DocumentBuilder;
 import javax.xml.parsers.DocumentBuilderFactory;
 import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.stream.FactoryConfigurationError;
+import javax.xml.stream.XMLInputFactory;
+import javax.xml.stream.XMLStreamConstants;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.XMLStreamReader;
 import javax.xml.transform.OutputKeys;
 import javax.xml.transform.Source;
 import javax.xml.transform.Transformer;
@@ -39,7 +45,9 @@ import javax.xml.transform.TransformerFa
 import javax.xml.transform.dom.DOMSource;
 import javax.xml.transform.sax.SAXSource;
 import javax.xml.transform.stream.StreamResult;
+import javax.xml.transform.stream.StreamSource;
 
+import org.apache.commons.lang3.tuple.ImmutablePair;
 import org.apache.jmeter.assertions.AssertionResult;
 import org.apache.xml.utils.PrefixResolver;
 import org.apache.xpath.XPathAPI;
@@ -57,16 +65,44 @@ import org.xml.sax.InputSource;
 import org.xml.sax.SAXException;
 import org.xml.sax.SAXParseException;
 
+import com.github.benmanes.caffeine.cache.Caffeine;
+import com.github.benmanes.caffeine.cache.LoadingCache;
+
+import net.sf.saxon.s9api.Processor;
+import net.sf.saxon.s9api.SaxonApiException;
+import net.sf.saxon.s9api.XPathExecutable;
+import net.sf.saxon.s9api.XPathSelector;
+import net.sf.saxon.s9api.XdmItem;
+import net.sf.saxon.s9api.XdmNode;
+import net.sf.saxon.s9api.XdmValue;
+
 /**
  * This class provides a few utility methods for dealing with XML/XPath.
  */
 public class XPathUtil {
+
     private static final Logger log = LoggerFactory.getLogger(XPathUtil.class);
 
+    private static final LoadingCache<ImmutablePair<String, String>, XPathExecutable> XPATH_CACHE;
+    static {
+        final int cacheSize = JMeterUtils.getPropDefault(
+                "xpath2query.parser.cache.size", 400);
+        XPATH_CACHE = Caffeine.newBuilder().maximumSize(cacheSize).build(new XPathQueryCacheLoader());
+    }
+
+    /**
+     * 
+     */
+    private static final Processor PROCESSOR = new Processor(false);
+
     private XPathUtil() {
         super();
     }
 
+    public static Processor getProcessor() {
+        return PROCESSOR;
+    }
+
     private static DocumentBuilderFactory documentBuilderFactory;
 
     /**
@@ -141,7 +177,7 @@ public class XPathUtil {
      */
     public static Document makeDocument(InputStream stream, boolean validate, boolean whitespace, boolean namespace,
             boolean tolerant, boolean quiet, boolean showWarnings, boolean reportErrors, boolean isXml, boolean downloadDTDs)
-            throws ParserConfigurationException, SAXException, IOException, TidyException {
+                    throws ParserConfigurationException, SAXException, IOException, TidyException {
         return makeDocument(stream, validate, whitespace, namespace,
                 tolerant, quiet, showWarnings, reportErrors, isXml, downloadDTDs, null);
     }
@@ -169,7 +205,7 @@ public class XPathUtil {
     public static Document makeDocument(InputStream stream, boolean validate, boolean whitespace, boolean namespace,
             boolean tolerant, boolean quiet, boolean showWarnings, boolean report_errors, boolean isXml, boolean downloadDTDs, 
             OutputStream tidyOut)
-            throws ParserConfigurationException, SAXException, IOException, TidyException {
+                    throws ParserConfigurationException, SAXException, IOException, TidyException {
         Document doc;
         if (tolerant) {
             doc = tidyDoc(stream, quiet, showWarnings, report_errors, isXml, tidyOut);
@@ -271,7 +307,7 @@ public class XPathUtil {
             }
         }
     }
-    
+
     /**
      * Return value for node including node element
      * @param node Node
@@ -288,7 +324,8 @@ public class XPathUtil {
         }
         return sw.toString();
     }
-    
+
+
     /**
      * @param node {@link Node}
      * @return String content of node
@@ -328,8 +365,9 @@ public class XPathUtil {
             List<String> matchStrings, boolean fragment) throws TransformerException {
         putValuesForXPathInList(document, xPathQuery, matchStrings, fragment, -1);
     }
-    
-    
+
+
+
     /**
      * Put in matchStrings results of evaluation
      * @param document XML document
@@ -339,10 +377,8 @@ public class XPathUtil {
      * @param matchNumber match number
      * @throws TransformerException when the internally used xpath engine fails
      */
-    public static void putValuesForXPathInList(Document document, 
-            String xPathQuery,
-            List<String> matchStrings, boolean fragment, 
-            int matchNumber) throws TransformerException {
+    public static void putValuesForXPathInList(Document document, String xPathQuery, List<String> matchStrings, boolean fragment, int matchNumber)
+            throws TransformerException {
         String val = null;
         XObject xObject = XPathAPI.eval(document, xPathQuery, getPrefixResolver(document));
         final int objectType = xObject.getType();
@@ -365,7 +401,7 @@ public class XPathUtil {
                         val = getValueForNode(match);
                     }
                 } else {
-                   val = match.getNodeValue();
+                    val = match.getNodeValue();
                 }
                 matchStrings.add(val);
             }
@@ -378,9 +414,147 @@ public class XPathUtil {
         } else {
             val = xObject.toString();
             matchStrings.add(val);
-      }
+        }
     }
 
+    public static void putValuesForXPathInListUsingSaxon(
+            String xmlFile, String xPathQuery, 
+            List<String> matchStrings, boolean fragment, 
+            int matchNumber, String namespaces)
+            throws SaxonApiException, FactoryConfigurationError {
+
+        // generating the cache key
+        final ImmutablePair<String, String> key = ImmutablePair.of(xPathQuery, namespaces);
+
+        //check the cache
+        XPathExecutable xPathExecutable;
+        if(!xPathQuery.equals("")) {
+            xPathExecutable = XPATH_CACHE.get(key);
+        }
+        else {
+            log.warn("Error : {}", JMeterUtils.getResString("xpath2_extractor_empty_query"));
+            return;
+        }
+
+        try (StringReader reader = new StringReader(xmlFile)) {
+            // We could instanciate it once but might trigger issues in the future 
+            // Sharing of a DocumentBuilder across multiple threads is not recommended. 
+            // However, in the current implementation sharing a DocumentBuilder (once initialized) 
+            // will only cause problems if a SchemaValidator is used.
+            net.sf.saxon.s9api.DocumentBuilder builder = PROCESSOR.newDocumentBuilder();
+            XdmNode xdmNode = builder.build(new StreamSource(reader));
+            
+            if(xPathExecutable!=null) {
+                XPathSelector selector = xPathExecutable.load();
+                selector.setContextItem(xdmNode);
+                XdmValue nodes = selector.evaluate();
+                int length = nodes.size();
+                int indexToMatch = matchNumber;
+                // In case we need to extract everything
+                if(matchNumber < 0) {
+                    for(XdmItem item : nodes) {
+                        if(fragment) {
+                            matchStrings.add(item.toString());
+                        }
+                        else {
+                            matchStrings.add(item.getStringValue());
+                        }
+                    }
+                } else {
+                    if(indexToMatch <= length) {
+                        if(matchNumber == 0 && length>0) {
+                            indexToMatch = JMeterUtils.getRandomInt(length)+1;
+                        } 
+                        XdmItem item = nodes.itemAt(indexToMatch-1);
+                        matchStrings.add(fragment ? item.toString() : item.getStringValue());
+                    } else {
+                        if(log.isWarnEnabled()) {
+                            log.warn("Error : {}{}", JMeterUtils.getResString("xpath2_extractor_match_number_failure"),indexToMatch);
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+
+    public static List<String[]> namespacesParse(String namespaces) {
+        List<String[]> res = new ArrayList<>();
+        int length = namespaces.length();
+        int startWord = 0;
+        boolean afterEqual = false;
+        int positionLastKey = -1;
+        for(int i = 0; i < length; i++) {
+            char actualChar = namespaces.charAt(i);
+            if(actualChar=='=' && !afterEqual) {
+                String [] tmp = new String[2];
+                tmp[0] = namespaces.substring(startWord, i);
+                res.add(tmp);
+                afterEqual = true;
+                startWord = i+1;
+                positionLastKey++;
+            }
+            else if(namespaces.charAt(i)=='\n' && afterEqual) {
+                afterEqual = false;
+                res.get(positionLastKey)[1]= namespaces.substring(startWord, i);
+                startWord = i+1;
+            }
+            else if(namespaces.charAt(i)=='\n') {
+                startWord = i+1;
+            }
+            else if(i==length-1 && afterEqual) {
+                res.get(positionLastKey)[1]= namespaces.substring(startWord, i+1);
+            }
+        }
+        return res;
+    }
+
+    public static List<String[]> getNamespaces(String xml)
+            throws XMLStreamException, FactoryConfigurationError{
+        List<String[]> res= new ArrayList<>();
+        XMLStreamReader reader;
+        if(!xml.equals("")) {
+            reader = XMLInputFactory.newFactory().createXMLStreamReader(new StringReader(xml));
+            while (reader.hasNext()) {
+                int event = reader.next();
+                if (XMLStreamConstants.START_ELEMENT == event) {
+                    addToList(reader, res);
+                } else if(XMLStreamConstants.NAMESPACE == event) {
+                    // This almost never happens
+                    addToList(reader, res);
+                }
+            }
+        }
+        return res;
+    }
+
+    private static void addToList(XMLStreamReader reader, List<String[]> res) {
+        boolean isInList = false;
+        int namespaceCount = reader.getNamespaceCount(); 
+        if (namespaceCount > 0) {
+            for (int nsIndex = 0; nsIndex < namespaceCount; nsIndex++) {
+                String[] tmp = {"",""};
+                String nsPrefix = reader.getNamespacePrefix(nsIndex);
+                for(int i = 0;i<res.size();i++) {
+                    String prefix = res.get(i)[0];
+                    if(prefix != null && prefix.equals(nsPrefix)) {
+                        isInList = true;
+                        break;
+                    }
+                }
+                if(!isInList) {
+                    String nsId = reader.getNamespaceURI(nsIndex);
+                    tmp[0] = nsPrefix;
+                    tmp[1] = nsId;
+                    res.add(tmp);
+                }
+                isInList=false;
+            }
+        }
+    }
+
+
+
     /**
      * 
      * @param document XML Document
@@ -420,37 +594,37 @@ public class XPathUtil {
         try {
             XObject xObject = XPathAPI.eval(doc, xPathExpression, getPrefixResolver(doc));
             switch (xObject.getType()) {
-                case XObject.CLASS_NODESET:
-                    NodeList nodeList = xObject.nodelist();
-                    final int len = (nodeList != null) ? nodeList.getLength() : 0;
-                    log.debug("nodeList length {}", len);
-                    // length == 0 means nodelist is null 
-                    if (len == 0) {
-                        log.debug("nodeList is null or empty. No match by xpath expression: {}", xPathExpression);
-                        result.setFailure(!isNegated);
-                        result.setFailureMessage("No Nodes Matched " + xPathExpression);
-                        return;
-                    }
-                    if (log.isDebugEnabled() && !isNegated) {
-                        for (int i = 0; i < len; i++) {
-                            log.debug("nodeList[{}]: {}", i, nodeList.item(i));
-                        }
-                    }
-                    result.setFailure(isNegated);
-                    if (isNegated) {
-                        result.setFailureMessage("Specified XPath was found... Turn off negate if this is not desired");
-                    }
+            case XObject.CLASS_NODESET:
+                NodeList nodeList = xObject.nodelist();
+                final int len = (nodeList != null) ? nodeList.getLength() : 0;
+                log.debug("nodeList length {}", len);
+                // length == 0 means nodelist is null 
+                if (len == 0) {
+                    log.debug("nodeList is null or empty. No match by xpath expression: {}", xPathExpression);
+                    result.setFailure(!isNegated);
+                    result.setFailureMessage("No Nodes Matched " + xPathExpression);
                     return;
-                case XObject.CLASS_BOOLEAN:
-                    if (!xObject.bool()){
-                        result.setFailure(!isNegated);
-                        result.setFailureMessage("No Nodes Matched " + xPathExpression);
+                }
+                if (log.isDebugEnabled() && !isNegated) {
+                    for (int i = 0; i < len; i++) {
+                        log.debug("nodeList[{}]: {}", i, nodeList.item(i));
                     }
-                    return;
-                default:
-                    result.setFailure(true);
-                    result.setFailureMessage("Cannot understand: " + xPathExpression);
-                    return;
+                }
+                result.setFailure(isNegated);
+                if (isNegated) {
+                    result.setFailureMessage("Specified XPath was found... Turn off negate if this is not desired");
+                }
+                return;
+            case XObject.CLASS_BOOLEAN:
+                if (!xObject.bool()){
+                    result.setFailure(!isNegated);
+                    result.setFailureMessage("No Nodes Matched " + xPathExpression);
+                }
+                return;
+            default:
+                result.setFailure(true);
+                result.setFailureMessage("Cannot understand: " + xPathExpression);
+                return;
             }
         } catch (TransformerException e) {
             result.setError(true);
@@ -462,7 +636,7 @@ public class XPathUtil {
                     .toString());
         }
     }
-    
+
     /**
      * Formats XML
      * @param xml string to format

Added: jmeter/trunk/test/resources/XPathUtilTestXml.xml
URL: http://svn.apache.org/viewvc/jmeter/trunk/test/resources/XPathUtilTestXml.xml?rev=1832784&view=auto
==============================================================================
--- jmeter/trunk/test/resources/XPathUtilTestXml.xml (added)
+++ jmeter/trunk/test/resources/XPathUtilTestXml.xml Sun Jun  3 19:05:08 2018
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Employees>
+    <Employee id="1">
+        <age:ag xmlns:age="http://www.w3.org/2003/01/geo/wgs84_pos#">29</age:ag>
+        <name>Pankaj</name>
+        <gender>Male</gender>
+        <role>Java Developer</role>
+    </Employee>
+    <Employee id="2">
+        <age:ag xmlns:age="http://www.w3.org/2003/01/geo/wgs84_pos#">35</age:ag>
+        <name>Lisa</name>
+        <gender>Female</gender>
+        <role>CEO</role>
+    </Employee>
+    <Employee id="3">
+        <age:ag xmlns:age="http://www.w3.org/2003/01/geo/wgs84_pos#">45</age:ag>
+        <name>Tom</name>
+        <gender>Male</gender>
+        <role>Manager</role>
+    </Employee>
+    <Employee id="4">
+        <age:ag xmlns:age="http://www.w3.org/2003/01/geo/wgs84_pos#">55</age:ag>
+        <name>Meghan</name>
+        <gender>Female</gender>
+        <role>Manager</role>
+    </Employee>
+</Employees>
\ No newline at end of file

Propchange: jmeter/trunk/test/resources/XPathUtilTestXml.xml
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: jmeter/trunk/test/resources/XPathUtilTestXml.xml
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Modified: jmeter/trunk/test/src/org/apache/jmeter/util/XPathUtilTest.java
URL: http://svn.apache.org/viewvc/jmeter/trunk/test/src/org/apache/jmeter/util/XPathUtilTest.java?rev=1832784&r1=1832783&r2=1832784&view=diff
==============================================================================
--- jmeter/trunk/test/src/org/apache/jmeter/util/XPathUtilTest.java (original)
+++ jmeter/trunk/test/src/org/apache/jmeter/util/XPathUtilTest.java Sun Jun  3 19:05:08 2018
@@ -18,17 +18,110 @@
 
 package org.apache.jmeter.util;
 
+import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertThat;
 
 import java.io.PrintStream;
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.xml.stream.FactoryConfigurationError;
 
 import org.hamcrest.CoreMatchers;
 import org.junit.Test;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
-public class XPathUtilTest {
+import net.sf.saxon.s9api.SaxonApiException;
 
+public class XPathUtilTest {
+    private static final Logger log = LoggerFactory.getLogger(XPathUtil.class);
     final String lineSeparator = System.getProperty("line.separator");
 
+    final String xmlDoc = JMeterUtils.getResourceFileAsText("XPathUtilTestXml.xml");
+    
+    @Test
+    public void testputValuesForXPathInListUsingSaxon(){
+        
+        String xPathQuery="//Employees/Employee/role";
+        ArrayList<String> matchStrings = new ArrayList<String>();
+        boolean fragment = false;
+        String namespaces = "age=http://www.w3.org/2003/01/geo/wgs84_pos#";
+        int matchNumber = 3;
+        
+        try {
+            XPathUtil.putValuesForXPathInListUsingSaxon(xmlDoc, xPathQuery, matchStrings, fragment, matchNumber, namespaces);
+            assertEquals("Manager",matchStrings.get(0));
+            
+            matchNumber = 0;
+            xPathQuery="//Employees/Employee[1]/age:ag";
+            fragment = true;
+            matchStrings.clear();
+            XPathUtil.putValuesForXPathInListUsingSaxon(xmlDoc, xPathQuery, matchStrings, fragment, matchNumber, namespaces);
+            assertEquals("<age:ag xmlns:age=\"http://www.w3.org/2003/01/geo/wgs84_pos#\">29</age:ag>",matchStrings.get(0));
+            assertEquals(1,matchStrings.size());
+            
+            matchNumber = -1;
+            xPathQuery="//Employees/Employee/age:ag";
+            matchStrings.clear();
+            XPathUtil.putValuesForXPathInListUsingSaxon(xmlDoc, xPathQuery, matchStrings, fragment, matchNumber, namespaces);
+            assertEquals("<age:ag xmlns:age=\"http://www.w3.org/2003/01/geo/wgs84_pos#\">29</age:ag>",matchStrings.get(0));
+            assertEquals(4,matchStrings.size());
+            
+            fragment = false;
+            matchStrings.clear();
+            XPathUtil.putValuesForXPathInListUsingSaxon(xmlDoc, xPathQuery, matchStrings, fragment, matchNumber, namespaces);
+            assertEquals("29",matchStrings.get(0));
+            assertEquals(4,matchStrings.size());
+            
+            matchStrings.clear();
+            xPathQuery="regtsgwsdfstgsdf";
+            XPathUtil.putValuesForXPathInListUsingSaxon(xmlDoc, xPathQuery, matchStrings, fragment, matchNumber, namespaces);
+            assertEquals(new ArrayList<String>(),matchStrings);
+            assertEquals(0,matchStrings.size());
+            
+            matchStrings.clear();
+            xPathQuery="//Employees/Employee[1]/age:ag";
+            matchNumber = 555;
+            XPathUtil.putValuesForXPathInListUsingSaxon(xmlDoc, xPathQuery, matchStrings, fragment, matchNumber, namespaces);
+            assertEquals(new ArrayList<String>(),matchStrings);
+            assertEquals(0,matchStrings.size());
+
+        } catch (SaxonApiException e) {
+            if (log.isWarnEnabled()) {
+                log.warn("SaxonApiException while processing ({}). {}", xPathQuery, e.getLocalizedMessage());
+            }
+        }catch(FactoryConfigurationError e) {
+            log.error("FactoryConfigurationError on {}", e);
+            log.warn("FactoryConfigurationError while processing {}", e.getLocalizedMessage());
+        }
+    }
+
+    @Test
+    public void testnamespacesParse() {
+        String namespaces = "donald=duck";
+        List<String[]> test = XPathUtil.namespacesParse(namespaces);
+        assertEquals("donald",test.get(0)[0]);
+        assertEquals("duck",test.get(0)[1]);
+        
+        namespaces = "donald=duck\nmickey=mouse";
+        test = XPathUtil.namespacesParse(namespaces);
+        assertEquals("donald",test.get(0)[0]);
+        assertEquals("duck",test.get(0)[1]);
+        assertEquals("mickey",test.get(1)[0]);
+        assertEquals("mouse",test.get(1)[1]);
+        
+        namespaces = "donald=duck\n\n\nmickey=mouse";
+        test = XPathUtil.namespacesParse(namespaces);
+        assertEquals("mickey",test.get(1)[0]);
+        assertEquals("mouse",test.get(1)[1]);
+        
+        namespaces = "geo=patate\n       \n   \n\nmickey=mouse\n\n      \n";
+        test = XPathUtil.namespacesParse(namespaces);
+        assertEquals("mickey",test.get(1)[0]);
+        assertEquals("mouse",test.get(1)[1]);
+    }
+
     @Test
     public void testFormatXmlSimple() {
         assertThat(XPathUtil.formatXml("<one foo='bar'>Test</one>"),
@@ -48,6 +141,7 @@ public class XPathUtilTest {
                         "  </three>...</one>",
                         "")));
     }
+    
 
     @Test()
     public void testFormatXmlInvalid() {

Modified: jmeter/trunk/xdocs/changes.xml
URL: http://svn.apache.org/viewvc/jmeter/trunk/xdocs/changes.xml?rev=1832784&r1=1832783&r2=1832784&view=diff
==============================================================================
--- jmeter/trunk/xdocs/changes.xml [utf-8] (original)
+++ jmeter/trunk/xdocs/changes.xml [utf-8] Sun Jun  3 19:05:08 2018
@@ -116,6 +116,7 @@ this behaviour, set <code>httpclient.res
 <h3>Timers, Assertions, Config, Pre- &amp; Post-Processors</h3>
 <ul>
     <li><bug>62320</bug>Counter : Reference Name property is not clear</li>
+    <li><bug>60991</bug>XPath Extractor : Implement XPath 2.0. Contributed by Ubik Load Pack (support at ubikloadpack.com)</li>
 </ul>
 
 <h3>Functions</h3>



Mime
View raw message