jmeter-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From pmoua...@apache.org
Subject svn commit: r1860513 - in /jmeter/trunk: bin/ src/components/org/apache/jmeter/assertions/ src/components/org/apache/jmeter/assertions/gui/ src/core/org/apache/jmeter/resources/ src/core/org/apache/jmeter/save/ src/core/org/apache/jmeter/util/ test/src...
Date Sun, 02 Jun 2019 10:51:24 GMT
Author: pmouawad
Date: Sun Jun  2 10:51:23 2019
New Revision: 1860513

URL: http://svn.apache.org/viewvc?rev=1860513&view=rev
Log:
Bug 62787 - Add XPath 2 Assertion

Contributed by UbikLoadPack (https://ubikloadpack.com)

This closes #459
Bugzilla Id: 62787

Added:
    jmeter/trunk/src/components/org/apache/jmeter/assertions/XPath2Assertion.java   (with props)
    jmeter/trunk/src/components/org/apache/jmeter/assertions/gui/XPath2AssertionGui.java   (with props)
    jmeter/trunk/src/components/org/apache/jmeter/assertions/gui/XPath2Panel.java   (with props)
    jmeter/trunk/src/core/org/apache/jmeter/util/PropertiesBasedPrefixResolverForXpath2.java   (with props)
    jmeter/trunk/test/src/org/apache/jmeter/assertions/XPath2AssertionTest.java   (with props)
Modified:
    jmeter/trunk/bin/saveservice.properties
    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/save/SaveService.java
    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

Modified: jmeter/trunk/bin/saveservice.properties
URL: http://svn.apache.org/viewvc/jmeter/trunk/bin/saveservice.properties?rev=1860513&r1=1860512&r2=1860513&view=diff
==============================================================================
--- jmeter/trunk/bin/saveservice.properties (original)
+++ jmeter/trunk/bin/saveservice.properties Sun Jun  2 10:51:23 2019
@@ -363,6 +363,8 @@ XMLSchemaAssertion=org.apache.jmeter.ass
 XMLSchemaAssertionGUI=org.apache.jmeter.assertions.gui.XMLSchemaAssertionGUI
 XPathAssertion=org.apache.jmeter.assertions.XPathAssertion
 XPathAssertionGui=org.apache.jmeter.assertions.gui.XPathAssertionGui
+XPath2Assertion=org.apache.jmeter.assertions.XPath2Assertion
+XPath2AssertionGui=org.apache.jmeter.assertions.gui.XPath2AssertionGui
 XPathExtractor=org.apache.jmeter.extractor.XPathExtractor
 XPathExtractorGui=org.apache.jmeter.extractor.gui.XPathExtractorGui
 XPath2Extractor=org.apache.jmeter.extractor.XPath2Extractor
@@ -418,4 +420,4 @@ _org.apache.jmeter.save.converters.TestR
 _org.apache.jmeter.save.ScriptWrapperConverter=mapping
 #
 #	Remember to update the _version entry
-#
+#
\ No newline at end of file

Added: jmeter/trunk/src/components/org/apache/jmeter/assertions/XPath2Assertion.java
URL: http://svn.apache.org/viewvc/jmeter/trunk/src/components/org/apache/jmeter/assertions/XPath2Assertion.java?rev=1860513&view=auto
==============================================================================
--- jmeter/trunk/src/components/org/apache/jmeter/assertions/XPath2Assertion.java (added)
+++ jmeter/trunk/src/components/org/apache/jmeter/assertions/XPath2Assertion.java Sun Jun  2 10:51:23 2019
@@ -0,0 +1,135 @@
+/*
+ * 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.assertions;
+
+import java.io.Serializable;
+
+import org.apache.commons.lang3.StringUtils;
+import org.apache.jmeter.samplers.SampleResult;
+import org.apache.jmeter.testelement.AbstractScopedAssertion;
+import org.apache.jmeter.testelement.property.BooleanProperty;
+import org.apache.jmeter.testelement.property.StringProperty;
+import org.apache.jmeter.util.XPathUtil;
+
+import net.sf.saxon.s9api.SaxonApiException;
+
+/**
+ * Checks if the result is a well-formed XML content and whether it matches an
+ * XPath
+ *
+ */
+public class XPath2Assertion extends AbstractScopedAssertion implements Serializable, Assertion {
+    private static final long serialVersionUID = 241L;
+    // + JMX file attributes
+    private static final String XPATH_KEY = "XPath.xpath"; // $NON-NLS-1$
+    private static final String VALIDATE_KEY = "XPath.validate"; // $NON-NLS-1$
+    private static final String NEGATE_KEY = "XPath.negate"; // $NON-NLS-1$
+    private static final String NAMESPACES = "XPath.namespaces"; // $NON-NLS-1$
+    // - JMX file attributes
+    public static final String DEFAULT_XPATH = "/";
+
+    /**
+     * Returns the result of the Assertion. Checks if the result is well-formed XML,
+     * and that the XPath expression is matched (or not, as the case may be)
+     */
+    @Override
+    public AssertionResult getResult(SampleResult response) {
+        // no error as default
+        AssertionResult result = new AssertionResult(getName());
+        result.setFailure(false);
+        result.setFailureMessage("");
+        String responseData = null;
+        if (isScopeVariable()) {
+            String inputString = getThreadContext().getVariables().get(getVariableName());
+            if (!StringUtils.isEmpty(inputString)) {
+                responseData = inputString;
+            }
+        } else {
+            responseData = response.getResponseDataAsString();
+        }
+        if (responseData == null) {
+            return result.setResultForNull();
+        }
+        try {
+            XPathUtil.computeAssertionResultUsingSaxon(result, responseData, getXPathString(),
+                    getNamespaces(),isNegated());
+        } catch (SaxonApiException e) {
+            result.setError(true);
+            result.setFailureMessage("SaxonApiException occured computing assertion with XPath:" + getXPathString() + ", error:" + e.getMessage());
+            return result;
+        }
+        return result;
+    }
+
+    /**
+     * Get The XPath String that will be used in matching the document
+     *
+     * @return String xpath String
+     */
+    public String getXPathString() {
+        return getPropertyAsString(XPATH_KEY, DEFAULT_XPATH);
+    }
+
+    /**
+     * Set the XPath String this will be used as an xpath
+     *
+     * @param xpath String
+     */
+    public void setXPathString(String xpath) {
+        setProperty(new StringProperty(XPATH_KEY, xpath));
+    }
+
+    /**
+     * Set use validation
+     *
+     * @param validate Flag whether validation should be used
+     */
+    public void setValidating(boolean validate) {
+        setProperty(new BooleanProperty(VALIDATE_KEY, validate));
+    }
+
+    public void setNegated(boolean negate) {
+        setProperty(new BooleanProperty(NEGATE_KEY, negate));
+    }
+
+    /**
+     * Is this validating
+     *
+     * @return boolean
+     */
+    public boolean isValidating() {
+        return getPropertyAsBoolean(VALIDATE_KEY, false);
+    }
+
+    /**
+     * Negate the XPath test, that is return true if something is not found.
+     *
+     * @return boolean negated
+     */
+    public boolean isNegated() {
+        return getPropertyAsBoolean(NEGATE_KEY, false);
+    }
+
+    public void setNamespaces(String namespaces) {
+        setProperty(NAMESPACES, namespaces);
+    }
+
+    public String getNamespaces() {
+        return getPropertyAsString(NAMESPACES);
+    }
+}

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

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

Added: jmeter/trunk/src/components/org/apache/jmeter/assertions/gui/XPath2AssertionGui.java
URL: http://svn.apache.org/viewvc/jmeter/trunk/src/components/org/apache/jmeter/assertions/gui/XPath2AssertionGui.java?rev=1860513&view=auto
==============================================================================
--- jmeter/trunk/src/components/org/apache/jmeter/assertions/gui/XPath2AssertionGui.java (added)
+++ jmeter/trunk/src/components/org/apache/jmeter/assertions/gui/XPath2AssertionGui.java Sun Jun  2 10:51:23 2019
@@ -0,0 +1,124 @@
+/*
+ * 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.assertions.gui;
+
+import java.awt.BorderLayout;
+
+import javax.swing.BorderFactory;
+import javax.swing.Box;
+import javax.swing.JPanel;
+
+import org.apache.jmeter.assertions.XPath2Assertion;
+import org.apache.jmeter.gui.GUIMenuSortOrder;
+import org.apache.jmeter.testelement.TestElement;
+import org.apache.jmeter.util.JMeterUtils;
+
+@GUIMenuSortOrder(50)
+public class XPath2AssertionGui extends AbstractAssertionGui { // $NOSONAR
+
+    private static final long serialVersionUID = 240L;// $NON-NLS-1$
+    private XPath2Panel xpath;
+
+
+    public XPath2AssertionGui() {
+        super();
+        init();
+    }
+
+    /**
+     * Returns the label to be shown within the JTree-Component.
+     */
+    @Override
+    public String getLabelResource() {
+        return "xpath2_assertion_title"; //$NON-NLS-1$
+    }
+
+    /**
+     * Create test element
+     */
+    @Override
+    public TestElement createTestElement() {
+        XPath2Assertion el = new XPath2Assertion();
+        modifyTestElement(el);
+        return el;
+    }
+
+    public String getXPathAttributesTitle() {
+        return JMeterUtils.getResString("xpath2_assertion_test"); //$NON-NLS-1$
+    }
+
+    @Override
+    public void configure(TestElement el) {
+        super.configure(el);
+        XPath2Assertion assertion = (XPath2Assertion) el;
+        showScopeSettings(assertion, true);
+        xpath.setXPath(assertion.getXPathString());
+        xpath.setNegated(assertion.isNegated());
+        xpath.setNamespaces(assertion.getNamespaces());
+    }
+
+    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 topBox = Box.createVerticalBox();
+
+        topBox.add(makeTitlePanel());
+
+        topBox.add(createScopePanel(true));
+        add(topBox, BorderLayout.NORTH);
+
+        // USER_INPUT
+        JPanel sizePanel = new JPanel(new BorderLayout());
+        sizePanel.setBorder(BorderFactory.createEmptyBorder(0, 10, 10, 10));
+        sizePanel.setBorder(BorderFactory.createTitledBorder(BorderFactory.createEtchedBorder(),
+                getXPathAttributesTitle()));
+        xpath = new XPath2Panel();
+        sizePanel.add(xpath);
+        add(sizePanel, BorderLayout.CENTER);
+    }
+    /**
+     * Modifies a given TestElement to mirror the data in the gui components.
+     *
+     * @see org.apache.jmeter.gui.JMeterGUIComponent#modifyTestElement(TestElement)
+     */
+    @Override
+    public void modifyTestElement(TestElement el) {
+        super.configureTestElement(el);
+        if (el instanceof XPath2Assertion) {
+            XPath2Assertion assertion = (XPath2Assertion) el;
+            saveScopeSettings(assertion);
+            assertion.setNegated(xpath.isNegated());
+            assertion.setXPathString(xpath.getXPath());
+            assertion.setNamespaces(xpath.getNamespaces());
+        }
+    }
+
+    /**
+     * Implements JMeterGUIComponent.clearGui
+     */
+    @Override
+    public void clearGui() {
+        super.clearGui();
+        xpath.setXPath("/"); //$NON-NLS-1$
+        xpath.setNegated(false);
+        xpath.setNamespaces("");
+    }
+
+}

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

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

Added: jmeter/trunk/src/components/org/apache/jmeter/assertions/gui/XPath2Panel.java
URL: http://svn.apache.org/viewvc/jmeter/trunk/src/components/org/apache/jmeter/assertions/gui/XPath2Panel.java?rev=1860513&view=auto
==============================================================================
--- jmeter/trunk/src/components/org/apache/jmeter/assertions/gui/XPath2Panel.java (added)
+++ jmeter/trunk/src/components/org/apache/jmeter/assertions/gui/XPath2Panel.java Sun Jun  2 10:51:23 2019
@@ -0,0 +1,260 @@
+/*
+ * 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.assertions.gui;
+
+import java.awt.BorderLayout;
+import java.awt.GridBagConstraints;
+import java.awt.GridBagLayout;
+
+import javax.swing.Box;
+import javax.swing.JButton;
+import javax.swing.JCheckBox;
+import javax.swing.JLabel;
+import javax.swing.JOptionPane;
+import javax.swing.JPanel;
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.transform.TransformerException;
+
+import org.apache.jmeter.gui.util.JSyntaxTextArea;
+import org.apache.jmeter.gui.util.JTextScrollPane;
+import org.apache.jmeter.util.JMeterUtils;
+import org.apache.jmeter.util.XPathUtil;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+
+/**
+ * Gui component for representing a xpath expression
+ *
+ */
+public class XPath2Panel extends JPanel {
+    private static final long serialVersionUID = 241L;
+
+    private static final Logger log = LoggerFactory.getLogger(XPath2Panel.class);
+
+    private JCheckBox negated;
+
+    private JSyntaxTextArea xpath;
+
+    private JButton checkXPath;
+    
+    private JSyntaxTextArea namespacesTA;
+    public String getNamespaces() {
+        return this.namespacesTA.getText();
+    }
+
+    public void setNamespaces(String namespaces) {
+        this.namespacesTA.setText(namespaces);
+    }
+
+    /**
+     * 
+     */
+    public XPath2Panel() {
+        super();
+        init();
+    }
+
+    private void init() { // WARNING: called from ctor so must not be overridden (i.e. must be private or
+                          // final)
+        setLayout(new BorderLayout());
+        Box topBox = Box.createVerticalBox();   
+        Box box = Box.createHorizontalBox();
+        box.add(getNegatedCheckBox());
+        box.add(Box.createHorizontalGlue());
+        box.add(getCheckXPathButton());
+        box.add(Box.createHorizontalGlue());
+        box.add(Box.createHorizontalGlue());
+        box.add(Box.createHorizontalGlue());
+        topBox.add(box);       
+        topBox.add(makeParameterPanel());
+        add(topBox, BorderLayout.NORTH);
+        add(JTextScrollPane.getInstance(getXPathField()), BorderLayout.CENTER);
+        setDefaultValues();
+    }
+    private JPanel makeParameterPanel() {
+        JPanel panel = new JPanel(new GridBagLayout());
+        GridBagConstraints gbc = new GridBagConstraints();
+        initConstraints(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);
+
+        return panel;
+    }
+    private void resetContraints(GridBagConstraints gbc) {
+        gbc.gridx = 0;
+        gbc.gridy++;
+        gbc.weightx = 0;
+        gbc.gridwidth = 1;
+        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;
+    }
+    /**
+     * Set default values on this component
+     */
+    public void setDefaultValues() {
+        setXPath("/"); //$NON-NLS-1$
+        setNegated(false);
+    }
+
+    /**
+     * Get the XPath String
+     * 
+     * @return String
+     */
+    public String getXPath() {
+        return this.xpath.getText();
+    }
+
+    /**
+     * Set the string that will be used in the xpath evaluation
+     * 
+     * @param xpath The string representing the xpath expression
+     */
+    public void setXPath(String xpath) {
+        this.xpath.setInitialText(xpath);
+    }
+
+    /**
+     * Does this negate the xpath results
+     * 
+     * @return boolean
+     */
+    public boolean isNegated() {
+        return this.negated.isSelected();
+    }
+
+    /**
+     * Set this to true, if you want success when the xpath does not match.
+     * 
+     * @param negated Flag whether xpath match should be negated
+     */
+    public void setNegated(boolean negated) {
+        this.negated.setSelected(negated);
+    }
+
+    /**
+     * Negated chechbox
+     * 
+     * @return JCheckBox
+     */
+    public JCheckBox getNegatedCheckBox() {
+        if (negated == null) {
+            negated = new JCheckBox(JMeterUtils.getResString("xpath2_assertion_negate"), false); //$NON-NLS-1$
+        }
+
+        return negated;
+    }
+
+    /**
+     * Check XPath button
+     * 
+     * @return JButton
+     */
+    public JButton getCheckXPathButton() {
+        if (checkXPath == null) {
+            checkXPath = new JButton(JMeterUtils.getResString("xpath2_assertion_button")); //$NON-NLS-1$
+            checkXPath.addActionListener(e -> validXPath(xpath.getText(), true, this.getNamespaces()));
+        }
+        return checkXPath;
+    }
+
+    /**
+     * Returns the current {@link JSyntaxTextArea} for the xpath expression, or
+     * creates a new one, if none is found.
+     * 
+     * @return {@link JSyntaxTextArea} for the xpath expression
+     */
+    public JSyntaxTextArea getXPathField() {
+        if (xpath == null) {
+            xpath = JSyntaxTextArea.getInstance(20, 80);
+            xpath.setLanguage("xpath"); //$NON-NLS-1$
+        }
+        return xpath;
+    }
+
+    /**
+     * @return Returns the showNegate.
+     */
+    public boolean isShowNegated() {
+        return this.getNegatedCheckBox().isVisible();
+    }
+
+    /**
+     * @param showNegate
+     *            The showNegate to set.
+     */
+    public void setShowNegated(boolean showNegate) {
+        getNegatedCheckBox().setVisible(showNegate);
+    }
+
+    /**
+     * Test whether an XPath is valid. It seems the Xalan has no easy way to
+     * check, so this creates a dummy test document, then tries to evaluate the xpath against it.
+     * 
+     * @param xpathString
+     *            XPath String to validate
+     * @param showDialog
+     *            weather to show a dialog
+     * @return returns true if valid, false otherwise.
+     */
+    public static boolean validXPath(String xpathString, boolean showDialog,String namespaces) {
+        String ret = null;
+        boolean success = true;
+        Document testDoc = null;
+        try {
+            testDoc = XPathUtil.makeDocumentBuilder(false, false, false, false).newDocument();
+            Element el = testDoc.createElement("root"); //$NON-NLS-1$
+            testDoc.appendChild(el);
+            XPathUtil.validateXPath2(testDoc, xpathString, namespaces);
+        } catch (IllegalArgumentException | ParserConfigurationException | TransformerException e) {
+            log.warn("Exception while validating XPath.", e);
+            success = false;
+            ret = e.getLocalizedMessage();
+        }
+        if (showDialog) {
+            JOptionPane.showMessageDialog(null, 
+                    success ? JMeterUtils.getResString("xpath_assertion_valid") : ret, //$NON-NLS-1$
+                    success ? JMeterUtils.getResString("xpath_assertion_valid") : //$NON-NLS-1$
+                        JMeterUtils.getResString("xpath_assertion_failed"), //$NON-NLS-1$
+                        success ? JOptionPane.INFORMATION_MESSAGE //$NON-NLS-1$
+                                : JOptionPane.ERROR_MESSAGE);
+        }
+        return success;
+
+    }
+  
+    
+}

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

Propchange: jmeter/trunk/src/components/org/apache/jmeter/assertions/gui/XPath2Panel.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=1860513&r1=1860512&r2=1860513&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  2 10:51:23 2019
@@ -1472,6 +1472,11 @@ xpath_extractor_user_namespaces=<html>Na
 xpath_extractor_title=XPath Extractor
 xpath_file_file_name=XML file to get values from 
 xpath_tester=XPath Tester
+xpath2_assertion_button=Validate xpath expression
+xpath2_assertion_negate=Invert assertion(will fail if above conditions met)
+xpath2_assertion_option=XML Parsing Options
+xpath2_assertion_test=XPath2 Assertion
+xpath2_assertion_title=XPath2 Assertion
 xpath2_tester=XPath2 Tester
 xpath_namespaces=Show namespaces aliases
 xpath_tester_button_test=Test

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=1860513&r1=1860512&r2=1860513&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  2 10:51:23 2019
@@ -1461,6 +1461,11 @@ xpath_extractor_user_namespaces=Liste de
 xpath_extractor_title=Extracteur XPath
 xpath_file_file_name=Fichier XML contenant les valeurs
 xpath_tester=Testeur XPath
+xpath2_assertion_button=Valider l'expression xpath
+xpath2_assertion_negate=Inverser l'assertion (échouera si les conditions ci-dessus sont remplies)
+xpath2_assertion_option=Options d'analyse XML
+xpath2_assertion_test=Vérificateur XPath2
+xpath2_assertion_title=Assertion XPath2
 xpath2_tester=Testeur XPath2
 xpath_namespaces=Voir alias namespaces
 xpath_tester_button_test=Tester

Modified: jmeter/trunk/src/core/org/apache/jmeter/save/SaveService.java
URL: http://svn.apache.org/viewvc/jmeter/trunk/src/core/org/apache/jmeter/save/SaveService.java?rev=1860513&r1=1860512&r2=1860513&view=diff
==============================================================================
--- jmeter/trunk/src/core/org/apache/jmeter/save/SaveService.java (original)
+++ jmeter/trunk/src/core/org/apache/jmeter/save/SaveService.java Sun Jun  2 10:51:23 2019
@@ -156,7 +156,7 @@ public class SaveService {
     private static String fileVersion = ""; // computed from saveservice.properties file// $NON-NLS-1$
     // Must match the sha1 checksum of the file saveservice.properties (without newline character),
     // used to ensure saveservice.properties and SaveService are updated simultaneously
-    static final String FILEVERSION = "e922e4aa06ed9f253d68c13f445d5bfedaccd876"; // Expected value $NON-NLS-1$
+    static final String FILEVERSION = "822c168ccf18e482d4be1915456c0b503b6f3d75"; // Expected value $NON-NLS-1$
 
     private static String fileEncoding = ""; // read from properties file// $NON-NLS-1$
 

Added: jmeter/trunk/src/core/org/apache/jmeter/util/PropertiesBasedPrefixResolverForXpath2.java
URL: http://svn.apache.org/viewvc/jmeter/trunk/src/core/org/apache/jmeter/util/PropertiesBasedPrefixResolverForXpath2.java?rev=1860513&view=auto
==============================================================================
--- jmeter/trunk/src/core/org/apache/jmeter/util/PropertiesBasedPrefixResolverForXpath2.java (added)
+++ jmeter/trunk/src/core/org/apache/jmeter/util/PropertiesBasedPrefixResolverForXpath2.java Sun Jun  2 10:51:23 2019
@@ -0,0 +1,65 @@
+/*
+ * 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.HashMap;
+import java.util.Map;
+
+import org.apache.xml.utils.PrefixResolver;
+import org.apache.xml.utils.PrefixResolverDefault;
+import org.w3c.dom.Node;
+
+/**
+ * {@link PrefixResolver} implementation that loads prefix configuration from
+ * jmeter property xpath.namespace.config
+ */
+public class PropertiesBasedPrefixResolverForXpath2 extends PrefixResolverDefault {
+    private Map<String, String> namespace_map = new HashMap<>();
+
+    /**
+     * @param xpathExpressionContext Node
+     */
+    public PropertiesBasedPrefixResolverForXpath2(Node xpathExpressionContext, String namespace) {
+        super(xpathExpressionContext);
+        namespace_map.clear();
+        namespace = namespace.trim();
+        if (!namespace.isEmpty()) {
+            for (String n : namespace.split("\\s+")) {
+                String[] keyandvalue = n.trim().split("=");
+                namespace_map.put(keyandvalue[0], keyandvalue[1]);
+            }
+        }
+    }
+
+    /**
+     * Searches prefix in NAMESPACE_MAP, if it fails to find it defaults to parent
+     * implementation
+     * 
+     * @param prefix           Prefix
+     * @param namespaceContext Node
+     */
+    @Override
+    public String getNamespaceForPrefix(String prefix, Node namespaceContext) {
+        String namespace = namespace_map.get(prefix);
+        if (namespace == null) {
+            return super.getNamespaceForPrefix(prefix, namespaceContext);
+        } else {
+            return namespace;
+        }
+    }
+}

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

Propchange: jmeter/trunk/src/core/org/apache/jmeter/util/PropertiesBasedPrefixResolverForXpath2.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=1860513&r1=1860512&r2=1860513&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  2 10:51:23 2019
@@ -75,7 +75,6 @@ import net.sf.saxon.s9api.XdmValue;
 
 import com.github.benmanes.caffeine.cache.Caffeine;
 import com.github.benmanes.caffeine.cache.LoadingCache;
-
 /**
  * This class provides a few utility methods for dealing with XML/XPath.
  */
@@ -590,6 +589,29 @@ public class XPathUtil {
     }
 
     /**
+     * 
+     * @param document XML Document
+     * @return {@link PrefixResolver}
+     */
+    private static PrefixResolver getPrefixResolverForXPath2(Document document,String namespaces) {
+        return new PropertiesBasedPrefixResolverForXpath2(document.getDocumentElement(),namespaces);
+    }
+    /**
+     * Validate xpathString is a valid XPath expression
+     * @param document XML Document
+     * @param xpathString XPATH String
+     * @throws TransformerException if expression fails to evaluate
+     */
+    public static void validateXPath2(Document document, String xpathString,String namespaces) throws TransformerException {
+        if (XPathAPI.eval(document, xpathString, getPrefixResolverForXPath2(document,namespaces)) == null) {
+            // We really should never get here
+            // because eval will throw an exception
+            // if xpath is invalid, but whatever, better
+            // safe
+            throw new IllegalArgumentException("xpath eval of '" + xpathString + "' was null");
+        }
+    }
+    /**
      * Fills result
      * @param result {@link AssertionResult}
      * @param doc XML Document
@@ -646,6 +668,75 @@ public class XPathUtil {
                     .toString());
         }
     }
+    
+  
+    /***
+    *
+    * @param result     The result of xpath2 assertion
+    * @param xmlFile
+    * @param xPathQuery
+    * @param namespaces
+    * @throws SaxonApiException
+    * @throws FactoryConfigurationError
+    */
+   public static void computeAssertionResultUsingSaxon(AssertionResult result, String xmlFile, String xPathQuery,
+           String namespaces, Boolean isNegated) throws SaxonApiException, FactoryConfigurationError {
+       // generating the cache key
+       final ImmutablePair<String, String> key = ImmutablePair.of(xPathQuery, namespaces);
+       // check the cache
+       XPathExecutable xPathExecutable;
+       if (StringUtils.isNotEmpty(xPathQuery)) {
+           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 SAXSource(new InputSource(reader)));
+           if (xPathExecutable != null) {
+               XPathSelector selector = null;
+               try {
+                   Document doc;
+                   doc = XPathUtil.makeDocumentBuilder(false, false, false, false).newDocument();
+                   XObject xObject = XPathAPI.eval(doc, xPathQuery, getPrefixResolverForXPath2(doc, namespaces));
+                   selector = xPathExecutable.load();
+                   selector.setContextItem(xdmNode);
+                   XdmValue nodes = selector.evaluate();
+                   boolean resultOfEval = true;
+                   int length = nodes.size();
+                   // In case we need to extract everything
+                   if (length == 0) {
+                       resultOfEval = false;
+                   } else if (xObject.getType() == XObject.CLASS_BOOLEAN) {
+                       resultOfEval = Boolean.valueOf(nodes.itemAt(0).getStringValue());
+                   }
+                   result.setFailure(isNegated ? resultOfEval : !resultOfEval);
+                   result.setFailureMessage(
+                           isNegated ? "Nodes Matched for " + xPathQuery : "No Nodes Matched for " + xPathQuery);
+               } catch (ParserConfigurationException | TransformerException e) {
+                   result.setError(true);
+                   result.setFailureMessage(new StringBuilder("Exception: ").append(e.getMessage()).append(" for:")
+                           .append(xPathQuery).toString());
+               } finally {
+                   if (selector != null) {
+                       try {
+                           selector.getUnderlyingXPathContext().setContextItem(null);
+                       } catch (Exception e) { // NOSONAR Ignored on purpose
+                           result.setError(true);
+                           result.setFailureMessage(new StringBuilder("Exception: ").append(e.getMessage())
+                                   .append(" for:").append(xPathQuery).toString());
+                       }
+                   }
+               }
+           }
+       }
+   }
 
     /**
      * Formats XML

Added: jmeter/trunk/test/src/org/apache/jmeter/assertions/XPath2AssertionTest.java
URL: http://svn.apache.org/viewvc/jmeter/trunk/test/src/org/apache/jmeter/assertions/XPath2AssertionTest.java?rev=1860513&view=auto
==============================================================================
--- jmeter/trunk/test/src/org/apache/jmeter/assertions/XPath2AssertionTest.java (added)
+++ jmeter/trunk/test/src/org/apache/jmeter/assertions/XPath2AssertionTest.java Sun Jun  2 10:51:23 2019
@@ -0,0 +1,146 @@
+/*
+ * 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.assertions;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import javax.xml.parsers.FactoryConfigurationError;
+
+import org.apache.jmeter.samplers.SampleResult;
+import org.apache.jmeter.util.JMeterUtils;
+import org.junit.Test;
+
+public class XPath2AssertionTest {
+
+    final String xmlDoc = JMeterUtils.getResourceFileAsText("XPathUtilTestXml.xml");
+    @Test
+    public void testXPath2AssertionPath1() throws FactoryConfigurationError {
+        XPath2Assertion assertion = new XPath2Assertion();
+        SampleResult response = new SampleResult();
+        String namespaces = "age=http://www.w3.org/2003/01/geo/wgs84_pos#";
+        String xPathQuery = "//Employees/Employee[1]/age:ag";
+        assertion.setNamespaces(namespaces);
+        assertion.setXPathString(xPathQuery);
+        response.setResponseData(xmlDoc, "UTF-8");
+        AssertionResult res = assertion.getResult(response);
+        assertFalse("When xpath2 conforms to xml, the result of assertion should be true ",res.isFailure());
+        assertFalse("When the format of xpath2 is right, assertion will run correctly ",res.isError());
+    }
+    @Test
+    public void testXPath2AssertionPath1Negated() throws FactoryConfigurationError {
+        XPath2Assertion assertion = new XPath2Assertion();
+        SampleResult response = new SampleResult();
+        String namespaces = "age=http://www.w3.org/2003/01/geo/wgs84_pos#";
+        String xPathQuery = "//Employees/Employee[1]/age:ag";
+        assertion.setNamespaces(namespaces);
+        assertion.setXPathString(xPathQuery);
+        assertion.setNegated(true);
+        response.setResponseData(xmlDoc, "UTF-8");
+        AssertionResult res = assertion.getResult(response);
+        assertTrue("When xpath2 conforms to xml, the result of assertion should be false ",res.isFailure());
+        assertFalse("When the format of xpath2 is right, assertion will run correctly ",res.isError());
+
+    }
+    @Test
+    public void testXPath2AssertionPath2() throws FactoryConfigurationError {
+       XPath2Assertion assertion = new XPath2Assertion();
+        SampleResult response = new SampleResult();
+        String namespaces = "age=http://www.w3.org/2003/01/geo/wgs84#";
+        String xPathQuery = "//Employees/Employee[1]/age:ag";
+        assertion.setNamespaces(namespaces);
+        assertion.setXPathString(xPathQuery);
+        response.setResponseData(xmlDoc, "UTF-8");
+        AssertionResult res = assertion.getResult(response);
+        assertTrue("When xpath2 doesn't conform to xml, the result of assertion should be false ", res.isFailure());
+        assertFalse("When the format of xpath2 is right, assertion will run correctly ",res.isError());
+    }
+    @Test
+    public void testXPath2AssertionPath2Negated() throws FactoryConfigurationError {
+        XPath2Assertion assertion = new XPath2Assertion();
+        SampleResult response = new SampleResult();
+        String namespaces = "age=http://www.w3.org/2003/01/geo/wgs84#";
+        String xPathQuery = "//Employees/Employee[1]/age:ag";
+        assertion.setNamespaces(namespaces);
+        assertion.setXPathString(xPathQuery);
+        assertion.setNegated(true);
+        response.setResponseData(xmlDoc, "UTF-8");
+        AssertionResult res = assertion.getResult(response);
+        assertFalse("When xpath2 doesn't conform to xml, the result of assertion should be true ", res.isFailure());
+        assertFalse("When the format of xpath2 is right, assertion will run correctly ",res.isError());
+
+    }
+    
+    @Test
+    public void testXPath2AssertionBool1() throws FactoryConfigurationError {
+       XPath2Assertion assertion = new XPath2Assertion();
+        SampleResult response = new SampleResult();
+        String namespaces = "age=http://www.w3.org/2003/01/geo/wgs84_pos#";
+        String xPathQuery = "count(//Employee)=4";
+        assertion.setNamespaces(namespaces);
+        assertion.setXPathString(xPathQuery);
+        response.setResponseData(xmlDoc, "UTF-8");
+        AssertionResult res = assertion.getResult(response);
+        assertFalse("When xpath2 conforms to xml, the result of assertion should be true ",res.isFailure());
+        assertFalse("When the format of xpath2 is right, assertion will run correctly ",res.isError());
+    }
+    @Test
+    public void testXPath2AssertionBool1Negated() throws FactoryConfigurationError {
+        XPath2Assertion assertion = new XPath2Assertion();
+        SampleResult response = new SampleResult();
+        String namespaces = "age=http://www.w3.org/2003/01/geo/wgs84_pos#";
+        String xPathQuery = "count(//Employee)=4";
+        assertion.setNamespaces(namespaces);
+        assertion.setXPathString(xPathQuery);
+        assertion.setNegated(true);
+        response.setResponseData(xmlDoc, "UTF-8");
+        AssertionResult res = assertion.getResult(response);
+        assertTrue("When xpath2 conforms to xml, the result of assertion should be false ",res.isFailure());
+        assertFalse("When the format of xpath2 is right, assertion will run correctly ",res.isError());
+    }
+    @Test
+    public void testXPath2AssertionBool2() throws FactoryConfigurationError {
+        XPath2Assertion assertion = new XPath2Assertion();
+        SampleResult response = new SampleResult();
+        String namespaces = "age=http://www.w3.org/2003/01/geo/wgs84_pos#";
+        String xPathQuery = "count(//Employee)=3";  //Wrong
+        assertion.setNamespaces(namespaces);
+        assertion.setXPathString(xPathQuery);
+        response.setResponseData(xmlDoc, "UTF-8");
+        AssertionResult res = assertion.getResult(response);
+        assertTrue("When xpath2 doesn't conforms to xml, the result of assertion should be false ",res.isFailure());
+        assertFalse("When the format of xpath2 is right, assertion will run correctly ",res.isError());
+    }
+    @Test
+    public void testXPath2AssertionBool2Negated() throws FactoryConfigurationError {
+        XPath2Assertion assertion = new XPath2Assertion();
+        SampleResult response = new SampleResult();
+        String namespaces = "age=http://www.w3.org/2003/01/geo/wgs84_pos#";
+        String xPathQuery = "count(//Employee)=3";  //Wrong
+        assertion.setNamespaces(namespaces);
+        assertion.setXPathString(xPathQuery);
+        assertion.setNegated(true);
+        response.setResponseData(xmlDoc, "UTF-8");
+        AssertionResult res = assertion.getResult(response);
+        assertFalse("When xpath2 doesn't conforms to xml, the result of assertion should be true ",res.isFailure());
+        assertFalse("When the format of xpath2 is right, assertion will run correctly ",res.isError());
+    }
+          
+
+}

Propchange: jmeter/trunk/test/src/org/apache/jmeter/assertions/XPath2AssertionTest.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: jmeter/trunk/test/src/org/apache/jmeter/assertions/XPath2AssertionTest.java
------------------------------------------------------------------------------
    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=1860513&r1=1860512&r2=1860513&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  2 10:51:23 2019
@@ -19,20 +19,27 @@
 package org.apache.jmeter.util;
 
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertThat;
+import static org.junit.Assert.assertTrue;
 
 import java.io.PrintStream;
 import java.io.StringReader;
 import java.util.ArrayList;
 import java.util.List;
 
+import javax.xml.parsers.ParserConfigurationException;
 import javax.xml.stream.FactoryConfigurationError;
 import javax.xml.transform.stream.StreamSource;
 
+import org.apache.jmeter.assertions.XPath2Assertion;
+import org.apache.jmeter.assertions.gui.XPath2Panel;
 import org.hamcrest.CoreMatchers;
 import org.junit.Test;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
 
 import net.sf.saxon.s9api.Processor;
 import net.sf.saxon.s9api.SaxonApiException;
@@ -47,13 +54,13 @@ public class XPathUtilTest {
     final String lineSeparator = System.getProperty("line.separator");
 
     final String xmlDoc = JMeterUtils.getResourceFileAsText("XPathUtilTestXml.xml");
-    
+    private XPath2Assertion assertion;
     @Test
     public void testBug63033() throws SaxonApiException {
         Processor p = new Processor(false);
         XPathCompiler c = p.newXPathCompiler();
         c.declareNamespace("age", "http://www.w3.org/2003/01/geo/wgs84_pos#");
-        String xPathQuery="//Employees/Employee[1]/age:ag";;
+        String xPathQuery="//Employees/Employee[1]/age:ag";
         XPathExecutable e = c.compile(xPathQuery);
         XPathSelector selector = e.load();
         selector.setContextItem(p.newDocumentBuilder().build(new StreamSource(new StringReader(xmlDoc))));
@@ -165,4 +172,18 @@ public class XPathUtilTest {
                 .is(XPathUtil.formatXml("No well formed xml here")));
         System.setErr(origErr);
     }
+    
+    @Test()
+    public void testValidateXPath2() throws ParserConfigurationException {
+        Document testDoc=XPathUtil.makeDocumentBuilder(false, false, false, false).newDocument();
+        Element el = testDoc.createElement("root"); //$NON-NLS-1$
+        testDoc.appendChild(el);
+        String namespaces = "a=http://www.w3.org/2003/01/geo/wgs84_pos# b=http://www.w3.org/2003/01/geo/wgs85_pos#";
+        String xPathQuery = "//Employees/b:Employee[1]/a:ag";
+        assertTrue("When the user give namspaces, the result of validation should be true", XPath2Panel.validXPath(xPathQuery, false, namespaces));
+        namespaces ="a=http://www.w3.org/2003/01/geo/wgs84_pos#";
+        assertFalse("When the user doesn't give namspaces, the result of validation should be false", XPath2Panel.validXPath(xPathQuery, false, namespaces));
+}
+    
+
 }

Modified: jmeter/trunk/xdocs/changes.xml
URL: http://svn.apache.org/viewvc/jmeter/trunk/xdocs/changes.xml?rev=1860513&r1=1860512&r2=1860513&view=diff
==============================================================================
--- jmeter/trunk/xdocs/changes.xml [utf-8] (original)
+++ jmeter/trunk/xdocs/changes.xml [utf-8] Sun Jun  2 10:51:23 2019
@@ -103,6 +103,7 @@ to view the last major behaviors with th
 <ul>
   <li><bug>62863</bug>Enable PKCS11 keystores for usage with KeyStore Manager. Based on patch by Clifford Harms (clifford.harms at gmail.com).</li>
   <li><pr>457</pr>Slight performance improvement in PoissonRandomTimer by using ThreadLocalRandom. Based on a patch by Xia Li.</li>
+  <li><bug>62787</bug>Add XPath 2 Assertion. Contributed by Ubik Load Pack (support at ubikloadpack.com)</li>
 </ul>
 
 <h3>Functions</h3>

Modified: jmeter/trunk/xdocs/usermanual/component_reference.xml
URL: http://svn.apache.org/viewvc/jmeter/trunk/xdocs/usermanual/component_reference.xml?rev=1860513&r1=1860512&r2=1860513&view=diff
==============================================================================
--- jmeter/trunk/xdocs/usermanual/component_reference.xml (original)
+++ jmeter/trunk/xdocs/usermanual/component_reference.xml Sun Jun  2 10:51:23 2019
@@ -4722,6 +4722,30 @@ prefix2=http\://toto.apache.org
 </ul>
 </note>
 </component>
+
+<component name="XPath2 Assertion" index="&sect-num;.5.16"  width="871" height="615" screenshot="xpath_assertion.png">
+<description><p>The XPath2 Assertion tests a document for well formedness.  Using "<code>/</code>" will match any well-formed
+document, and is the default XPath2 Expression. 
+The assertion also supports boolean expressions, such as "<code>count(//*error)=2</code>".
+</p>
+Some sample expressions:
+<ul>
+<li><code>//title[text()='Text to match']</code> - matches <code>&lt;title&gt;Text to match&lt;/title&gt;</code> anywhere in the response</li>
+<li><code>/title[text()='Text to match']</code> - matches <code>&lt;title&gt;Text to match&lt;/title&gt;</code> at root level in the response</li>
+</ul>
+</description>
+
+<properties>
+<property name="Namespaces aliases list" required="No">List of namespaces aliases you want to use to parse the document, one line per declaration.
+    You must specify them as follow : <code>prefix=namespace</code>. This implementation makes it easier to
+    use namespaces than with the old XPathExtractor version.</property>
+<property name="XPath2 Assertion"    required="Yes">XPath to match in the document.</property>
+<property name="Invert assertion"    required="No">Will fail if xpath expression returns true or matches, succeed otherwise</property>
+<property name="Namespace aliases list"    required="No">List of namespace aliases prefix=full namespace (one per line)</property>
+</properties>
+</component>
+
+
 <component name="XML Schema Assertion" index="&sect-num;.5.9"  width="472" height="132" screenshot="assertion/XMLSchemaAssertion.png">
 <description><p>The XML Schema Assertion allows the user to validate a response against an XML Schema.</p></description>
 



Mime
View raw message