public static void putValuesForXPathInListUsingSaxon(
            String xmlFile, String xPathQuery,
            List<? super 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(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 instantiate 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 {
                    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);
                            }
                        }
                    }
                } finally {
                    if(selector != null) {
                        try {
                            selector.getUnderlyingXPathContext().setContextItem(null);
                        } catch (Exception e) { // NOSONAR Ignored on purpose
                            // NOOP
                        }
                    }
                }
            }
        }
    }
@Test
    public void testputValuesForXPathInListUsingSaxon() throws SaxonApiException, FactoryConfigurationError{
        String xPathQuery="//Employees/Employee/role";
        ArrayList<String> matchStrings = new ArrayList<>();
        boolean fragment = false;
        String namespaces = "age=http://www.w3.org/2003/01/geo/wgs84_pos#";
        int matchNumber = 3;

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