SCXML-243: Remove XPath language support and cleanup engine implementation
- drop all xpath usages and commons jxpath dependency
- also drop no longer needed Evaluator.evalLocation method
- use Evaluator.cloneData method for creating invoke/send payload data copy
- no longer support XML node 'as string' for expression result
diff --git a/pom.xml b/pom.xml
index fbe52ce..50f60e7 100644
--- a/pom.xml
+++ b/pom.xml
@@ -170,11 +170,6 @@
       <optional>true</optional>
     </dependency>
     <dependency>
-      <groupId>commons-jxpath</groupId>
-      <artifactId>commons-jxpath</artifactId>
-      <version>1.3</version>
-    </dependency>
-    <dependency>
       <groupId>org.codehaus.groovy</groupId>
       <artifactId>groovy</artifactId>
       <version>2.2.2</version>
@@ -397,7 +392,7 @@
       </build>
     </profile>
     <profile>
-      <!-- download the W3C IRP tests and ecma and xpath stylesheets to transform them, using:
+      <!-- download the W3C IRP tests and ecma stylesheet to transform them, using:
            $ mvn -P w3Tests.get
        -->
       <id>w3cTests.get</id>
@@ -501,7 +496,7 @@
     </profile>
     <profile>
       <!-- Run one or multiple W3C IRP tests using optional system parameters for datamodel and/or test id, using:
-           $ mvn -P w3cTests.run [-Ddatamodel=<ecma|xpath|minimal>] [-Dtest=<testId>]
+           $ mvn -P w3cTests.run [-Ddatamodel=<ecma|minimal>] [-Dtest=<testId>]
 
            Also see: src/test/java/org/apache/commons/scxml2/w3c/tests.xml
            which contains configurations per test (if it default is enabled/disabled, status, etc.)
diff --git a/src/main/java/org/apache/commons/scxml2/Evaluator.java b/src/main/java/org/apache/commons/scxml2/Evaluator.java
index 0d7cad7..9878d0a 100644
--- a/src/main/java/org/apache/commons/scxml2/Evaluator.java
+++ b/src/main/java/org/apache/commons/scxml2/Evaluator.java
@@ -29,9 +29,6 @@
     /** SCXML 1.0 ECMAScript Data Model name **/
     String ECMASCRIPT_DATA_MODEL = "ecmascript";
 
-    /** SCXML 1.0 XPath Data Model name **/
-    String XPATH_DATA_MODEL = "xpath";
-
     /** Default Data Model name **/
     String DEFAULT_DATA_MODEL = "";
 
@@ -106,18 +103,6 @@
     throws SCXMLExpressionException;
 
     /**
-     * Evaluate a location that returns a data assignable reference or list of references.
-     * Manifests as "location" attributes of &lt;assign&gt; element.
-     *
-     * @param ctx variable context
-     * @param expr expression
-     * @return The location result.
-     * @throws SCXMLExpressionException A malformed expression exception
-     */
-    Object evalLocation(Context ctx, String expr)
-    throws SCXMLExpressionException;
-
-    /**
      * Assigns data to a location
      *
      * @param ctx variable context
diff --git a/src/main/java/org/apache/commons/scxml2/EvaluatorFactory.java b/src/main/java/org/apache/commons/scxml2/EvaluatorFactory.java
index e306e0a..bb2074b 100644
--- a/src/main/java/org/apache/commons/scxml2/EvaluatorFactory.java
+++ b/src/main/java/org/apache/commons/scxml2/EvaluatorFactory.java
@@ -23,7 +23,6 @@
 import org.apache.commons.scxml2.env.javascript.JSEvaluator;
 import org.apache.commons.scxml2.env.jexl.JexlEvaluator;
 import org.apache.commons.scxml2.env.minimal.MinimalEvaluator;
-import org.apache.commons.scxml2.env.xpath.XPathEvaluator;
 import org.apache.commons.scxml2.model.ModelException;
 import org.apache.commons.scxml2.model.SCXML;
 import static org.apache.commons.scxml2.Evaluator.DEFAULT_DATA_MODEL;
@@ -41,7 +40,6 @@
  *  <li>no or empty datamodel (default) or datamodel="jexl": {@link JexlEvaluator.JexlEvaluatorProvider}</li>
  *  <li>datamodel="ecmascript": {@link JSEvaluator.JSEvaluatorProvider}</li>
  *  <li>datamodel="groovy": {@link GroovyEvaluator.GroovyEvaluatorProvider}</li>
- *  <li>datamodel="xpath": {@link XPathEvaluator.XPathEvaluatorProvider}</li>
  *  <li>datamodel="null": {@link MinimalEvaluator.MinimalEvaluatorProvider}</li>
  * </ul>
  * <p>
@@ -58,10 +56,9 @@
 
     private static EvaluatorFactory INSTANCE = new EvaluatorFactory();
 
-    private final Map<String, EvaluatorProvider> providers = new ConcurrentHashMap<String, EvaluatorProvider>();
+    private final Map<String, EvaluatorProvider> providers = new ConcurrentHashMap<>();
 
     private EvaluatorFactory() {
-        providers.put(XPathEvaluator.SUPPORTED_DATA_MODEL, new XPathEvaluator.XPathEvaluatorProvider());
         providers.put(JSEvaluator.SUPPORTED_DATA_MODEL, new JSEvaluator.JSEvaluatorProvider());
         providers.put(GroovyEvaluator.SUPPORTED_DATA_MODEL, new GroovyEvaluator.GroovyEvaluatorProvider());
         providers.put(JexlEvaluator.SUPPORTED_DATA_MODEL, new JexlEvaluator.JexlEvaluatorProvider());
diff --git a/src/main/java/org/apache/commons/scxml2/SCInstance.java b/src/main/java/org/apache/commons/scxml2/SCInstance.java
index 1260fa4..39f2e11 100644
--- a/src/main/java/org/apache/commons/scxml2/SCInstance.java
+++ b/src/main/java/org/apache/commons/scxml2/SCInstance.java
@@ -25,9 +25,6 @@
 import java.util.Set;
 import java.util.UUID;
 
-import javax.xml.parsers.DocumentBuilderFactory;
-import javax.xml.parsers.ParserConfigurationException;
-
 import org.apache.commons.scxml2.env.SimpleContext;
 import org.apache.commons.scxml2.model.Data;
 import org.apache.commons.scxml2.model.Datamodel;
@@ -37,9 +34,6 @@
 import org.apache.commons.scxml2.model.SCXML;
 import org.apache.commons.scxml2.model.TransitionalState;
 import org.apache.commons.scxml2.semantics.ErrorConstants;
-import org.w3c.dom.Document;
-import org.w3c.dom.Element;
-import org.w3c.dom.Node;
 
 /**
  * The <code>SCInstance</code> performs book-keeping functions for
@@ -106,12 +100,12 @@
     /**
      * The map of contexts per EnterableState.
      */
-    private final Map<EnterableState, Context> contexts = new HashMap<EnterableState, Context>();
+    private final Map<EnterableState, Context> contexts = new HashMap<>();
 
     /**
      * The map of last known configurations per History.
      */
-    private final Map<History, Set<EnterableState>> histories = new HashMap<History, Set<EnterableState>>();
+    private final Map<History, Set<EnterableState>> histories = new HashMap<>();
 
     /**
      * The root context.
@@ -319,31 +313,7 @@
                     errorReporter.onError(ErrorConstants.EXPRESSION_ERROR, see.getMessage(), datum);
                     continue;
                 }
-                if (Evaluator.XPATH_DATA_MODEL.equals(evaluator.getSupportedDatamodel())) {
-                    try {
-                        Document document = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument();
-                        // TODO: should use SCXML namespace here?
-                        Element dataNode = document.createElement("data");
-                        dataNode.setAttribute("id", datum.getId());
-                        ctx.setLocal(datum.getId(), dataNode);
-                        evaluator.evalAssign(ctx, "$" + datum.getId(), value, Evaluator.AssignType.REPLACE_CHILDREN, null);
-                    }
-                    catch (ParserConfigurationException pce) {
-                        if (internalIOProcessor != null) {
-                            internalIOProcessor.addEvent(new TriggerEvent(TriggerEvent.ERROR_EXECUTION, TriggerEvent.ERROR_EVENT));
-                        }
-                        errorReporter.onError(ErrorConstants.EXECUTION_ERROR, pce.getMessage(), datum);
-                    }
-                    catch (SCXMLExpressionException see) {
-                        if (internalIOProcessor != null) {
-                            internalIOProcessor.addEvent(new TriggerEvent(TriggerEvent.ERROR_EXECUTION, TriggerEvent.ERROR_EVENT));
-                        }
-                        errorReporter.onError(ErrorConstants.EXPRESSION_ERROR, see.getMessage(), datum);
-                    }
-                }
-                else {
-                    ctx.setLocal(datum.getId(), value);
-                }
+                ctx.setLocal(datum.getId(), value);
             }
             else {
                 ctx.setLocal(datum.getId(), evaluator.cloneData(datum.getValue()));
@@ -422,7 +392,7 @@
             getRootContext();
             if (rootContext != null) {
                 Context internalContext = Evaluator.NULL_DATA_MODEL.equals(evaluator.getSupportedDatamodel()) ?
-                        new SimpleContext(systemContext) : evaluator.newContext(rootContext);
+                        new SimpleContext() : evaluator.newContext(rootContext);
                 systemContext = new SCXMLSystemContext(internalContext);
                 systemContext.getContext().set(SCXMLSystemContext.SESSIONID_KEY, UUID.randomUUID().toString());
                 String _name = stateMachine != null && stateMachine.getName() != null ? stateMachine.getName() : "";
@@ -524,7 +494,7 @@
      */
     public void setLastConfiguration(final History history,
             final Set<EnterableState> lc) {
-        histories.put(history, new HashSet<EnterableState>(lc));
+        histories.put(history, new HashSet<>(lc));
     }
 
     /**
diff --git a/src/main/java/org/apache/commons/scxml2/env/groovy/GroovyEvaluator.java b/src/main/java/org/apache/commons/scxml2/env/groovy/GroovyEvaluator.java
index c82d2d7..451ac42 100644
--- a/src/main/java/org/apache/commons/scxml2/env/groovy/GroovyEvaluator.java
+++ b/src/main/java/org/apache/commons/scxml2/env/groovy/GroovyEvaluator.java
@@ -222,35 +222,6 @@
     }
 
     /**
-     * @see Evaluator#evalLocation(Context, String)
-     */
-    @Override
-    public Object evalLocation(final Context ctx, final String expr) throws SCXMLExpressionException {
-        if (expr == null) {
-            return null;
-        }
-        else if (ctx.has(expr)) {
-            return expr;
-        }
-
-        if (!(ctx instanceof GroovyContext)) {
-            throw new SCXMLExpressionException(ERR_CTX_TYPE);
-        }
-
-        GroovyContext groovyCtx = (GroovyContext) ctx;
-        if (groovyCtx.getGroovyEvaluator() == null) {
-            groovyCtx.setGroovyEvaluator(this);
-        }
-        try {
-            final GroovyContext effective = getEffectiveContext(groovyCtx);
-            return getScript(effective, groovyCtx.getScriptBaseClass(), expr).run();
-        } catch (Exception e) {
-            String exMessage = e.getMessage() != null ? e.getMessage() : e.getClass().getCanonicalName();
-            throw new SCXMLExpressionException("evalLocation('" + expr + "'): " + exMessage, e);
-        }
-    }
-
-    /**
      * @see Evaluator#evalAssign(Context, String, Object, AssignType, String)
      */
     public void evalAssign(final Context ctx, final String location, final Object data, final AssignType type,
diff --git a/src/main/java/org/apache/commons/scxml2/env/javascript/JSEvaluator.java b/src/main/java/org/apache/commons/scxml2/env/javascript/JSEvaluator.java
index ca0d8eb..aa0a744 100644
--- a/src/main/java/org/apache/commons/scxml2/env/javascript/JSEvaluator.java
+++ b/src/main/java/org/apache/commons/scxml2/env/javascript/JSEvaluator.java
@@ -165,7 +165,7 @@
             Object ret = engine.eval(jsExpression, jsBindings);
 
             // copy global bindings attributes to context, so callers may get access to the evaluated variables.
-            copyGlobalBindingsToContext(jsBindings, (JSContext) effectiveContext);
+            copyGlobalBindingsToContext(jsBindings, effectiveContext);
 
             return ret;
 
@@ -202,29 +202,6 @@
     }
 
     /**
-     * Evaluates a location expression using a new Javascript engine obtained from
-     * factory instantiated in the constructor. The engine is supplied with
-     * a new JSBindings that includes the SCXML Context and SCXML builtin
-     * <code>In()</code> function is replaced with an equivalent internal
-     * Javascript function.
-     *
-     * @param context    FSM context.
-     * @param expression Expression to evaluate.
-     *
-     * @throws SCXMLExpressionException Thrown if the expression was invalid.
-     */
-    @Override
-    public Object evalLocation(Context context, String expression) throws SCXMLExpressionException {
-        if (expression == null) {
-            return null;
-        } else if (context.has(expression)) {
-            return expression;
-        }
-
-        return eval(context, expression);
-    }
-
-    /**
      * @see Evaluator#evalAssign(Context, String, Object, AssignType, String)
      */
     public void evalAssign(final Context ctx, final String location, final Object data, final AssignType type,
diff --git a/src/main/java/org/apache/commons/scxml2/env/jexl/JexlEvaluator.java b/src/main/java/org/apache/commons/scxml2/env/jexl/JexlEvaluator.java
index d08946c..af02a0b 100644
--- a/src/main/java/org/apache/commons/scxml2/env/jexl/JexlEvaluator.java
+++ b/src/main/java/org/apache/commons/scxml2/env/jexl/JexlEvaluator.java
@@ -192,31 +192,6 @@
     }
 
     /**
-     * @see Evaluator#evalLocation(Context, String)
-     */
-    public Object evalLocation(final Context ctx, final String expr)
-    throws SCXMLExpressionException {
-        if (expr == null) {
-            return null;
-        }
-        else if (ctx.has(expr)) {
-            return expr;
-        }
-
-        if (!(ctx instanceof JexlContext)) {
-            throw new SCXMLExpressionException(ERR_CTX_TYPE);
-        }
-        try {
-            final JexlContext effective = getEffectiveContext((JexlContext)ctx);
-            Expression exp = getJexlEngine().createExpression(expr);
-            return exp.evaluate(effective);
-        } catch (Exception e) {
-            String exMessage = e.getMessage() != null ? e.getMessage() : e.getClass().getCanonicalName();
-            throw new SCXMLExpressionException("evalLocation('" + expr + "'): " + exMessage, e);
-        }
-    }
-
-    /**
      * @see Evaluator#evalAssign(Context, String, Object, AssignType, String)
      */
     public void evalAssign(final Context ctx, final String location, final Object data, final AssignType type,
diff --git a/src/main/java/org/apache/commons/scxml2/env/minimal/MinimalEvaluator.java b/src/main/java/org/apache/commons/scxml2/env/minimal/MinimalEvaluator.java
index 66c18e5..0afefec 100644
--- a/src/main/java/org/apache/commons/scxml2/env/minimal/MinimalEvaluator.java
+++ b/src/main/java/org/apache/commons/scxml2/env/minimal/MinimalEvaluator.java
@@ -83,11 +83,6 @@
     }
 
     @Override
-    public Object evalLocation(final Context ctx, final String expr) throws SCXMLExpressionException {
-        return expr;
-    }
-
-    @Override
     public void evalAssign(final Context ctx, final String location, final Object data, final AssignType type, final String attr) throws SCXMLExpressionException {
         throw new UnsupportedOperationException("Assign expressions are not supported by the \"null\" datamodel");
     }
diff --git a/src/main/java/org/apache/commons/scxml2/env/xpath/ContextVariables.java b/src/main/java/org/apache/commons/scxml2/env/xpath/ContextVariables.java
deleted file mode 100644
index 03f38b1..0000000
--- a/src/main/java/org/apache/commons/scxml2/env/xpath/ContextVariables.java
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * 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.commons.scxml2.env.xpath;
-
-import org.apache.commons.jxpath.Variables;
-import org.apache.commons.scxml2.Context;
-
-/**
- * JXPath Variables mapping for SCXML Context
- */
-public class ContextVariables implements Variables {
-
-    private final Context ctx;
-
-    public ContextVariables(Context ctx) {
-        this.ctx = ctx;
-    }
-
-    @Override
-    public boolean isDeclaredVariable(final String varName) {
-        return ctx.has(varName);
-    }
-
-    @Override
-    public Object getVariable(final String varName) {
-        return ctx.get(varName);
-    }
-
-    @Override
-    public void declareVariable(final String varName, final Object value) {
-        ctx.set(varName, value);
-    }
-
-    @Override
-    public void undeclareVariable(final String varName) {
-        if (ctx.has(varName)) {
-            Context cctx = ctx;
-            while (!cctx.hasLocal(varName)) {
-                cctx = cctx.getParent();
-                if (cctx == null) {
-                    return;
-                }
-            }
-            cctx.getVars().remove(varName);
-        }
-    }
-}
diff --git a/src/main/java/org/apache/commons/scxml2/env/xpath/XPathContext.java b/src/main/java/org/apache/commons/scxml2/env/xpath/XPathContext.java
deleted file mode 100644
index f5881f7..0000000
--- a/src/main/java/org/apache/commons/scxml2/env/xpath/XPathContext.java
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
- * 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.commons.scxml2.env.xpath;
-
-import org.apache.commons.jxpath.Variables;
-import org.apache.commons.scxml2.Context;
-import org.apache.commons.scxml2.env.SimpleContext;
-
-/**
- * A {@link Context} implementation for JXPath environments.
- *
- */
-public class XPathContext extends SimpleContext
-implements Context, Variables {
-
-    /** Serial version UID. */
-    private static final long serialVersionUID = -6803159294612685806L;
-
-    /**
-     * No argument constructor.
-     *
-     */
-    public XPathContext() {
-        super();
-    }
-
-    /**
-     * Constructor for cascading contexts.
-     *
-     * @param parent The parent context. Can be null.
-     */
-    public XPathContext(final Context parent) {
-        super(parent);
-    }
-
-    @Override
-    public boolean isDeclaredVariable(final String varName) {
-        return has(varName);
-    }
-
-    @Override
-    public Object getVariable(final String varName) {
-        return get(varName);
-    }
-
-    @Override
-    public void declareVariable(final String varName, final Object value) {
-        set(varName, value);
-    }
-
-    @Override
-    public void undeclareVariable(final String varName) {
-        if (has(varName)) {
-            Context ctx = this;
-            while (!ctx.hasLocal(varName)) {
-                ctx = ctx.getParent();
-                if (ctx == null) {
-                    return;
-                }
-            }
-            ctx.getVars().remove(varName);
-        }
-    }
-}
diff --git a/src/main/java/org/apache/commons/scxml2/env/xpath/XPathEvaluator.java b/src/main/java/org/apache/commons/scxml2/env/xpath/XPathEvaluator.java
deleted file mode 100644
index 0da7103..0000000
--- a/src/main/java/org/apache/commons/scxml2/env/xpath/XPathEvaluator.java
+++ /dev/null
@@ -1,378 +0,0 @@
-/*
- * 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.commons.scxml2.env.xpath;
-
-import java.util.ArrayList;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-
-import org.apache.commons.jxpath.ClassFunctions;
-import org.apache.commons.jxpath.FunctionLibrary;
-import org.apache.commons.jxpath.Functions;
-import org.apache.commons.jxpath.JXPathContext;
-import org.apache.commons.jxpath.JXPathException;
-import org.apache.commons.jxpath.PackageFunctions;
-import org.apache.commons.jxpath.ri.model.NodePointer;
-import org.apache.commons.jxpath.ri.model.VariablePointer;
-import org.apache.commons.scxml2.Context;
-import org.apache.commons.scxml2.Evaluator;
-import org.apache.commons.scxml2.EvaluatorProvider;
-import org.apache.commons.scxml2.SCXMLExpressionException;
-import org.apache.commons.scxml2.env.AbstractBaseEvaluator;
-import org.apache.commons.scxml2.env.EffectiveContextMap;
-import org.apache.commons.scxml2.model.SCXML;
-import org.w3c.dom.Attr;
-import org.w3c.dom.CharacterData;
-import org.w3c.dom.Element;
-import org.w3c.dom.Node;
-import org.w3c.dom.NodeList;
-
-/**
- * <p>An {@link Evaluator} implementation for XPath environments.</p>
- *
- * <p>Does not support the &lt;script&gt; module, throws
- * {@link UnsupportedOperationException} if attempted.</p>
- */
-public class XPathEvaluator extends AbstractBaseEvaluator {
-
-    /** Serial version UID. */
-    private static final long serialVersionUID = -3578920670869493294L;
-
-    public static final String SUPPORTED_DATA_MODEL = Evaluator.XPATH_DATA_MODEL;
-
-    /**
-     * Internal 'marker' list used for collecting the NodePointer results of an {@link #evalLocation(Context, String)}
-     */
-    private static class NodePointerList extends ArrayList<NodePointer> {
-    }
-
-    public static class XPathEvaluatorProvider implements EvaluatorProvider {
-
-        @Override
-        public String getSupportedDatamodel() {
-            return SUPPORTED_DATA_MODEL;
-        }
-
-        @Override
-        public Evaluator getEvaluator() {
-            return new XPathEvaluator();
-        }
-
-        @Override
-        public Evaluator getEvaluator(final SCXML document) {
-            return new XPathEvaluator();
-        }
-    }
-
-    private static final JXPathContext jxpathRootContext = JXPathContext.newContext(null);
-
-    static {
-        FunctionLibrary xpathFunctions = new FunctionLibrary();
-        xpathFunctions.addFunctions(new ClassFunctions(XPathFunctions.class, null));
-        // also restore default generic JXPath functions
-        xpathFunctions.addFunctions(new PackageFunctions("", null));
-        jxpathRootContext.setFunctions(xpathFunctions);
-    }
-
-    private JXPathContext jxpathContext;
-
-    /**
-     * No argument constructor.
-     */
-    public XPathEvaluator() {
-        jxpathContext = jxpathRootContext;
-    }
-
-    /**
-     * Constructor supporting user-defined JXPath {@link Functions}.
-     *
-     * @param functions The user-defined JXPath functions to use.
-     */
-    public XPathEvaluator(final Functions functions) {
-        jxpathContext = JXPathContext.newContext(jxpathRootContext, null);
-        jxpathContext.setFunctions(functions);
-    }
-
-    @Override
-    public String getSupportedDatamodel() {
-        return SUPPORTED_DATA_MODEL;
-    }
-
-    /**
-     * @see Evaluator#eval(Context, String)
-     */
-    @Override
-    public Object eval(final Context ctx, final String expr)
-            throws SCXMLExpressionException {
-        try {
-            List list = getContext(ctx).selectNodes(expr);
-            if (list.isEmpty()) {
-                return null;
-            }
-            else if (list.size() == 1) {
-                return list.get(0);
-            }
-            return list;
-        } catch (JXPathException xee) {
-            throw new SCXMLExpressionException(xee.getMessage(), xee);
-        }
-    }
-
-    /**
-     * @see Evaluator#evalCond(Context, String)
-     */
-    @Override
-    public Boolean evalCond(final Context ctx, final String expr)
-            throws SCXMLExpressionException {
-        try {
-            return (Boolean)getContext(ctx).getValue(expr, Boolean.class);
-        } catch (JXPathException xee) {
-            throw new SCXMLExpressionException(xee.getMessage(), xee);
-        }
-    }
-
-    /**
-     * @see Evaluator#evalLocation(Context, String)
-     */
-    @Override
-    public Object evalLocation(final Context ctx, final String expr) throws SCXMLExpressionException {
-        JXPathContext context = getContext(ctx);
-        try {
-            Iterator iterator = context.iteratePointers(expr);
-            Object pointer;
-            NodePointerList pointerList = null;
-            while (iterator.hasNext()) {
-                pointer = iterator.next();
-                if (pointer != null && pointer instanceof NodePointer && ((NodePointer)pointer).getNode() != null) {
-                    if (pointerList == null) {
-                        pointerList = new NodePointerList();
-                    }
-                    pointerList.add((NodePointer)pointer);
-                }
-            }
-            return pointerList;
-        } catch (JXPathException xee) {
-            throw new SCXMLExpressionException(xee.getMessage(), xee);
-        }
-    }
-
-    /**
-     * @see Evaluator#evalAssign(Context, String, Object, AssignType, String)
-     */
-    public void evalAssign(final Context ctx, final String location, final Object data, final AssignType type,
-                           final String attr) throws SCXMLExpressionException {
-
-        Object loc = evalLocation(ctx, location);
-        if (isXPathLocation(ctx, loc)) {
-            assign(ctx, loc, data, type, attr);
-        }
-        else {
-            throw new SCXMLExpressionException("evalAssign - cannot resolve location: '" + location + "'");
-        }
-    }
-
-    /**
-     * @see Evaluator#evalScript(Context, String)
-     */
-    public Object evalScript(Context ctx, String script)
-    throws SCXMLExpressionException {
-        throw new UnsupportedOperationException("Scripts are not supported by the XPathEvaluator");
-    }
-
-    /**
-     * @see Evaluator#newContext(Context)
-     */
-    @Override
-    public Context newContext(final Context parent) {
-        return new XPathContext(parent);
-    }
-
-    /**
-     * Determine if an {@link Evaluator#evalLocation(Context, String)} returned result represents an XPath location
-     * @param ctx variable context
-     * @param data result data from {@link Evaluator#evalLocation(Context, String)}
-     * @return true if the data represents an XPath location
-     */
-    @SuppressWarnings("unused")
-    public boolean isXPathLocation(final Context ctx, Object data) {
-        return data instanceof NodePointerList;
-    }
-
-    /**
-     * Assigns data to a location
-     *
-     * @param ctx variable context
-     * @param location location expression
-     * @param data the data to assign.
-     * @param type the type of assignment to perform, null assumes {@link Evaluator.AssignType#REPLACE_CHILDREN}
-     * @param attr the name of the attribute to add when using type {@link Evaluator.AssignType#ADD_ATTRIBUTE}
-     * @throws SCXMLExpressionException A malformed expression exception
-     * @see Evaluator#evalAssign(Context, String, Object, Evaluator.AssignType, String)
-     */
-    public void assign(final Context ctx, final Object location, final Object data, final AssignType type,
-                       final String attr) throws SCXMLExpressionException {
-        if (!isXPathLocation(ctx, location)) {
-            throw new SCXMLExpressionException("assign requires a NodePointerList as location but is of type: " +
-                    (location==null ? "(null)" : location.getClass().getName()));
-        }
-        for (NodePointer pointer : (NodePointerList)location) {
-            Object node = pointer.getNode();
-            if (node != null) {
-                if (node instanceof Node) {
-                    assign(ctx, (Node)node, pointer.asPath(), data, type != null ? type : AssignType.REPLACE_CHILDREN, attr);
-                }
-                else if (pointer instanceof VariablePointer) {
-                    if (type == AssignType.DELETE) {
-                        pointer.remove();
-                    }
-                    VariablePointer vp = (VariablePointer)pointer;
-                    Object variable = vp.getNode();
-                    if (variable instanceof Node) {
-                        assign(ctx, (Node)variable, pointer.asPath(), data, type != null ? type : AssignType.REPLACE_CHILDREN, attr);
-                    }
-                    else if (type == null || type == AssignType.REPLACE) {
-                        String variableName = vp.getName().getName();
-                        if (data instanceof CharacterData) {
-                            ctx.set(variableName, ((CharacterData)data).getNodeValue());
-                        }
-                        else {
-                            ctx.set(variableName, data);
-                        }
-                    }
-                    else {
-                        throw new SCXMLExpressionException("Unsupported assign type +" +
-                                type.name()+" for XPath variable "+pointer.asPath());
-                    }
-                }
-                else {
-                    throw new SCXMLExpressionException("Unsupported XPath location pointer " +
-                            pointer.getClass().getName()+" for location "+pointer.asPath());
-                }
-            }
-            // else: silent ignore - NodePointerList should not have pointers without node
-        }
-    }
-
-    @SuppressWarnings("unused")
-    protected void assign(final Context ctx, final Node node, final String nodePath, final Object data,
-                          final AssignType type, final String attr) throws SCXMLExpressionException {
-
-        if (type == AssignType.DELETE) {
-            node.getParentNode().removeChild(node);
-        }
-        else if (node instanceof Element) {
-            Element element = (Element)node;
-            if (type == AssignType.ADD_ATTRIBUTE) {
-                if (attr == null) {
-                    throw new SCXMLExpressionException("Missing required attribute name for adding attribute at " +
-                            nodePath);
-                }
-                if (data == null) {
-                    throw new SCXMLExpressionException("Missing required data value for adding attribute " +
-                            attr + " to location " + nodePath);
-                }
-                element.setAttribute(attr, data.toString());
-            }
-            else {
-                Node dataNode = null;
-                if (type != AssignType.REPLACE_CHILDREN) {
-                    if (data == null) {
-                        throw new SCXMLExpressionException("Missing required data value for assign type "+type.name());
-                    }
-                    dataNode = data instanceof Node
-                            ? element.getOwnerDocument().importNode((Node)data, true)
-                            : element.getOwnerDocument().createTextNode(data.toString());
-                }
-                switch (type) {
-                    case REPLACE_CHILDREN:
-                        // quick way to delete all children
-                        element.setTextContent(null);
-                        if (data instanceof Node) {
-                            element.appendChild(element.getOwnerDocument().importNode((Node)data, true));
-                        }
-                        else if (data instanceof List) {
-                            for (Object dataElement : (List)data) {
-                                if (dataElement instanceof Node) {
-                                    element.appendChild(element.getOwnerDocument().importNode((Node)dataElement, true));
-                                }
-                                else if (dataElement != null) {
-                                    element.appendChild(element.getOwnerDocument().createTextNode(dataElement.toString()));
-                                }
-                            }
-                        }
-                        else if (data instanceof NodeList) {
-                            NodeList list = (NodeList)data;
-                            for (int i = 0, size = list.getLength(); i < size; i++)
-                            element.appendChild(element.getOwnerDocument().importNode(list.item(i), true));
-                        }
-                        else {
-                            element.appendChild(element.getOwnerDocument().createTextNode(data.toString()));
-                        }
-                        // else if data == null: already taken care of above
-                        break;
-                    case FIRST_CHILD:
-                        element.insertBefore(dataNode, element.getFirstChild());
-                        break;
-                    case LAST_CHILD:
-                        element.appendChild(dataNode);
-                        break;
-                    case PREVIOUS_SIBLING:
-                        element.getParentNode().insertBefore(dataNode, element);
-                        break;
-                    case NEXT_SIBLING:
-                        element.getParentNode().insertBefore(dataNode, element.getNextSibling());
-                        break;
-                    case REPLACE:
-                        element.getParentNode().replaceChild(dataNode, element);
-                        break;
-                }
-            }
-        }
-        else if (node instanceof CharacterData) {
-            if (type != AssignType.REPLACE) {
-                throw new SCXMLExpressionException("Assign type "+ type.name() +
-                        " not supported for character data node at " + nodePath);
-            }
-            ((CharacterData)node).setData(data.toString());
-        }
-        else if (node instanceof Attr) {
-            if (type != AssignType.REPLACE) {
-                throw new SCXMLExpressionException("Assign type "+ type.name() +
-                        " not supported for node attribute at " + nodePath);
-            }
-            ((Attr)node).setValue(data.toString());
-        }
-        else {
-            throw new SCXMLExpressionException("Unsupported assign location Node type "+node.getNodeType());
-        }
-    }
-
-
-    @SuppressWarnings("unchecked")
-    protected JXPathContext getContext(final Context ctx) throws SCXMLExpressionException {
-        JXPathContext context = JXPathContext.newContext(jxpathContext, new EffectiveContextMap(ctx));
-        context.setVariables(new ContextVariables(ctx));
-        Map<String, String> namespaces = (Map<String, String>) ctx.get(Context.NAMESPACES_KEY);
-        if (namespaces != null) {
-            for (String prefix : namespaces.keySet()) {
-                context.registerNamespace(prefix, namespaces.get(prefix));
-            }
-        }
-        return context;
-    }
-}
diff --git a/src/main/java/org/apache/commons/scxml2/env/xpath/XPathFunctions.java b/src/main/java/org/apache/commons/scxml2/env/xpath/XPathFunctions.java
deleted file mode 100644
index 277ec73..0000000
--- a/src/main/java/org/apache/commons/scxml2/env/xpath/XPathFunctions.java
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * 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.commons.scxml2.env.xpath;
-
-import java.util.Map;
-
-import org.apache.commons.jxpath.ExpressionContext;
-import org.apache.commons.jxpath.Variables;
-import org.apache.commons.scxml2.SCXMLSystemContext;
-import org.apache.commons.scxml2.Status;
-
-/**
- * Commons JXPath custom extension function providing the SCXML In() predicate
- */
-public class XPathFunctions {
-
-    /**
-     * Provides the SCXML standard In() predicate for SCXML documents.
-     * @param expressionContext The context currently in use for evaluation
-     * @param state The State ID to compare with
-     * @return true if this state is currently active
-     */
-    @SuppressWarnings("unchecked")
-    public static boolean In(ExpressionContext expressionContext, String state) {
-        Variables variables = expressionContext.getJXPathContext().getVariables();
-        Map<String,Object> platformVariables = (Map<String, Object>)variables.getVariable(SCXMLSystemContext.X_KEY);
-        return ((Status)platformVariables.get(SCXMLSystemContext.STATUS_KEY)).isInState(state);
-    }
-}
diff --git a/src/main/java/org/apache/commons/scxml2/env/xpath/package.html b/src/main/java/org/apache/commons/scxml2/env/xpath/package.html
deleted file mode 100644
index 071a79d..0000000
--- a/src/main/java/org/apache/commons/scxml2/env/xpath/package.html
+++ /dev/null
@@ -1,26 +0,0 @@
-<html>
-<!-- 
- * 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.
--->
-<head>
-</head>
-<body>
-
-  <p>A collection of classes that allow XPath to be used in expressions
-     within SCXML documents via Commons JXPath</p>
-
-</body>
-</html>
diff --git a/src/main/java/org/apache/commons/scxml2/model/Action.java b/src/main/java/org/apache/commons/scxml2/model/Action.java
index 6194ea1..550ddf0 100644
--- a/src/main/java/org/apache/commons/scxml2/model/Action.java
+++ b/src/main/java/org/apache/commons/scxml2/model/Action.java
@@ -22,7 +22,6 @@
 import org.apache.commons.scxml2.ActionExecutionContext;
 import org.apache.commons.scxml2.Context;
 import org.apache.commons.scxml2.SCXMLExpressionException;
-import org.w3c.dom.Node;
 
 /**
  * An abstract base class for executable elements in SCXML,
@@ -139,18 +138,5 @@
     protected static String getNamespacesKey() {
         return Context.NAMESPACES_KEY;
     }
-
-    /**
-     * Convenient method to convert a possible {@link Node} result from an expression evaluation to a String
-     * using its {@link Node#getTextContent()} method.
-     * @param result the result to convert
-     * @return its text content if the result is a {@link Node} otherwise the unmodified result itself
-     */
-    protected Object getTextContentIfNodeResult(final Object result) {
-        if (result instanceof Node) {
-            return ((Node)result).getTextContent();
-        }
-        return result;
-    }
 }
 
diff --git a/src/main/java/org/apache/commons/scxml2/model/Cancel.java b/src/main/java/org/apache/commons/scxml2/model/Cancel.java
index 0e9af87..16d9900 100644
--- a/src/main/java/org/apache/commons/scxml2/model/Cancel.java
+++ b/src/main/java/org/apache/commons/scxml2/model/Cancel.java
@@ -98,7 +98,7 @@
 
         String sendidValue = sendid;
         if (sendidValue == null && sendidexpr != null) {
-            sendidValue = (String) getTextContentIfNodeResult(eval.eval(ctx, sendidexpr));
+            sendidValue = (String) eval.eval(ctx, sendidexpr);
             if ((sendidValue == null || sendidValue.trim().length() == 0)
                     && exctx.getAppLog().isWarnEnabled()) {
                 exctx.getAppLog().warn("<send>: sendid expression \"" + sendidexpr
diff --git a/src/main/java/org/apache/commons/scxml2/model/Invoke.java b/src/main/java/org/apache/commons/scxml2/model/Invoke.java
index 8384ef1..34cc22c 100644
--- a/src/main/java/org/apache/commons/scxml2/model/Invoke.java
+++ b/src/main/java/org/apache/commons/scxml2/model/Invoke.java
@@ -344,7 +344,7 @@
 
             String typeValue = type;
             if (typeValue == null && typeexpr != null) {
-                typeValue = (String) getTextContentIfNodeResult(eval.eval(ctx, typeexpr));
+                typeValue = (String)eval.eval(ctx, typeexpr);
                 if (typeValue == null) {
                     throw new SCXMLExpressionException("<invoke> for state "+parentState.getId() +
                             ": type expression \"" + typeexpr + "\" evaluated to null or empty String");
@@ -366,7 +366,7 @@
 
             String src = getSrc();
             if (src == null && getSrcexpr() != null) {
-                src = (String) getTextContentIfNodeResult(eval.eval(ctx, getSrcexpr()));
+                src = (String)eval.eval(ctx, getSrcexpr());
             }
             if (src != null) {
                 PathResolver pr = getPathResolver();
@@ -393,7 +393,7 @@
                 throw new SCXMLExpressionException("<invoke> for state "+parentState.getId() +
                         ": no src and no content defined");
             }
-            Map<String, Object> payloadDataMap = new HashMap<String, Object>();
+            Map<String, Object> payloadDataMap = new HashMap<>();
             addNamelistDataToPayload(axctx, payloadDataMap);
             addParamsToPayload(axctx, payloadDataMap);
             invoker.setParentSCXMLExecutor(exctx.getSCXMLExecutor());
diff --git a/src/main/java/org/apache/commons/scxml2/model/Log.java b/src/main/java/org/apache/commons/scxml2/model/Log.java
index c6ad9e7..e27e039 100644
--- a/src/main/java/org/apache/commons/scxml2/model/Log.java
+++ b/src/main/java/org/apache/commons/scxml2/model/Log.java
@@ -95,7 +95,7 @@
         Context ctx = exctx.getContext(getParentEnterableState());
         Evaluator eval = exctx.getEvaluator();
         ctx.setLocal(getNamespacesKey(), getNamespaces());
-        exctx.getAppLog().info(label + ": " + String.valueOf(getTextContentIfNodeResult(eval.eval(ctx, expr))));
+        exctx.getAppLog().info(label + ": " + String.valueOf(eval.eval(ctx, expr)));
         ctx.setLocal(getNamespacesKey(), null);
     }
 }
diff --git a/src/main/java/org/apache/commons/scxml2/model/NamelistHolder.java b/src/main/java/org/apache/commons/scxml2/model/NamelistHolder.java
index 3145db7..74324aa 100644
--- a/src/main/java/org/apache/commons/scxml2/model/NamelistHolder.java
+++ b/src/main/java/org/apache/commons/scxml2/model/NamelistHolder.java
@@ -74,7 +74,6 @@
                 ctx.setLocal(getNamespacesKey(), getNamespaces());
                 Evaluator evaluator = exctx.getEvaluator();
                 StringTokenizer tkn = new StringTokenizer(namelist);
-                boolean xpathEvaluator = Evaluator.XPATH_DATA_MODEL.equals(evaluator.getSupportedDatamodel());
                 while (tkn.hasMoreTokens()) {
                     String varName = tkn.nextToken();
                     Object varObj = evaluator.eval(ctx, varName);
@@ -83,10 +82,7 @@
                         exctx.getErrorReporter().onError(ErrorConstants.UNDEFINED_VARIABLE,
                                 varName + " = null", parentState);
                     }
-                    if (xpathEvaluator && varName.startsWith("$")) {
-                        varName = varName.substring(1);
-                    }
-                    addToPayload(varName, varObj, payload);
+                    addToPayload(varName, evaluator.cloneData(varObj), payload);
                 }
             }
             finally {
diff --git a/src/main/java/org/apache/commons/scxml2/model/ParamsContainer.java b/src/main/java/org/apache/commons/scxml2/model/ParamsContainer.java
index 28d74c3..f37fabc 100644
--- a/src/main/java/org/apache/commons/scxml2/model/ParamsContainer.java
+++ b/src/main/java/org/apache/commons/scxml2/model/ParamsContainer.java
@@ -74,7 +74,7 @@
                         // ignore invalid param definition
                         continue;
                     }
-                    addToPayload(p.getName(), paramValue, payload);
+                    addToPayload(p.getName(), evaluator.cloneData(paramValue), payload);
                 }
             }
             finally {
diff --git a/src/main/java/org/apache/commons/scxml2/model/PayloadProvider.java b/src/main/java/org/apache/commons/scxml2/model/PayloadProvider.java
index 639acf3..84ae749 100644
--- a/src/main/java/org/apache/commons/scxml2/model/PayloadProvider.java
+++ b/src/main/java/org/apache/commons/scxml2/model/PayloadProvider.java
@@ -17,16 +17,9 @@
 package org.apache.commons.scxml2.model;
 
 import java.util.ArrayList;
-import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 
-import javax.xml.parsers.DocumentBuilderFactory;
-import javax.xml.parsers.ParserConfigurationException;
-
-import org.apache.commons.scxml2.Evaluator;
-import org.w3c.dom.Document;
-import org.w3c.dom.Element;
 import org.w3c.dom.Node;
 import org.w3c.dom.NodeList;
 
@@ -73,7 +66,7 @@
                 payload.put(attrName, valueList);
             }
         }
-        value = clonePayloadValue(attrValue);
+        value = attrValue;
         if (value instanceof List) {
             if (valueList == null) {
                 valueList = new DataValueList();
@@ -88,101 +81,4 @@
             payload.put(attrName, value);
         }
     }
-
-    /**
-     * Clones a value object for adding to a payload data map.
-     * <p>
-     * Currently only clones {@link Node} values.
-     * </p>
-     * <p>
-     * If the value object is an instanceof {@link NodeList}, {@link List} or {@link Map}, its elements
-     * are also cloned (if possible) through recursive invocation of this same method, and put in
-     * a new {@link List} or {@link Map} before returning.
-     * </p>
-     * @param value the value to be cloned
-     * @return the cloned value if it could be cloned or otherwise the unmodified value parameter
-     */
-    @SuppressWarnings("unchecked")
-    protected Object clonePayloadValue(final Object value) {
-        if (value != null) {
-            if (value instanceof Node) {
-                return ((Node)value).cloneNode(true);
-            }
-            else if (value instanceof NodeList) {
-                NodeList nodeList = (NodeList)value;
-                ArrayList<Node> list = new ArrayList<Node>();
-                for (int i = 0, size = nodeList.getLength(); i < size; i++) {
-                    list.add(nodeList.item(i).cloneNode(true));
-                }
-                return list;
-            }
-            else if (value instanceof List) {
-                ArrayList<Object> list = new ArrayList<Object>();
-                for (Object v : (List)value) {
-                    list.add(clonePayloadValue(v));
-                }
-                return list;
-            }
-            else if (value instanceof Map) {
-                HashMap<Object, Object> map = new HashMap<Object, Object>();
-                for (Map.Entry<Object,Object> entry : ((Map<Object,Object>)value).entrySet()) {
-                    map.put(entry.getKey(), clonePayloadValue(entry.getValue()));
-                }
-                return map;
-            }
-            // TODO: cloning other type of data?
-        }
-        return value;
-    }
-
-    /**
-     * Converts a payload data map to be used for an event payload.
-     * <p>
-     * Event payload involving key-value pair attributes for an xpath datamodel requires special handling as the
-     * attributes needs to be contained and put in a "data" element under a 'root' Event payload element.
-     * </p>
-     * <p>
-     * For non-xpath datamodels this method simply returns the original payload parameter unmodified.
-     * </p>
-     * @param evaluator the evaluator to test for which datamodel type this event payload is intended
-     * @param payload the payload data map
-     * @return payload for an event
-     * @throws ModelException if it fails to create payload or data node
-     */
-    protected Object makeEventPayload(final Evaluator evaluator, final Map<String, Object> payload)
-            throws ModelException {
-        if (payload != null && !payload.isEmpty() && Evaluator.XPATH_DATA_MODEL.equals(evaluator.getSupportedDatamodel())) {
-
-            try {
-                Document document = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument();
-                Element payloadNode = document.createElement("payload");
-                for (Map.Entry<String, Object> entry : payload.entrySet()) {
-                    Element dataNode = document.createElement("data");
-                    payloadNode.appendChild(dataNode);
-                    dataNode.setAttribute("id", entry.getKey());
-                    if (entry.getValue() instanceof Node) {
-                        dataNode.appendChild(document.importNode((Node)entry.getValue(), true));
-                    }
-                    else if (entry.getValue() instanceof DataValueList) {
-                        for (Object value : ((DataValueList)entry.getValue())) {
-                            if (value instanceof Node) {
-                                dataNode.appendChild(document.importNode((Node)entry.getValue(), true));
-                            }
-                            else {
-                                dataNode.setTextContent(String.valueOf(value));
-                            }
-                        }
-                    }
-                    else if (entry.getValue() != null) {
-                        dataNode.setTextContent(String.valueOf(entry.getValue()));
-                    }
-                }
-                return payloadNode;
-            }
-            catch (ParserConfigurationException pce) {
-                throw new ModelException("Cannot instantiate a DocumentBuilder", pce);
-            }
-        }
-        return payload;
-    }
 }
diff --git a/src/main/java/org/apache/commons/scxml2/model/Send.java b/src/main/java/org/apache/commons/scxml2/model/Send.java
index 1b63ce7..8a8dd2d 100644
--- a/src/main/java/org/apache/commons/scxml2/model/Send.java
+++ b/src/main/java/org/apache/commons/scxml2/model/Send.java
@@ -363,7 +363,7 @@
         }
         String targetValue = target;
         if (targetValue == null && targetexpr != null) {
-            targetValue = (String) getTextContentIfNodeResult(eval.eval(ctx, targetexpr));
+            targetValue = (String)eval.eval(ctx, targetexpr);
             if ((targetValue == null || targetValue.trim().length() == 0)
                     && exctx.getAppLog().isWarnEnabled()) {
                 exctx.getAppLog().warn("<send>: target expression \"" + targetexpr
@@ -372,7 +372,7 @@
         }
         String typeValue = type;
         if (typeValue == null && typeexpr != null) {
-            typeValue = (String) getTextContentIfNodeResult(eval.eval(ctx, typeexpr));
+            typeValue = (String)eval.eval(ctx, typeexpr);
             if ((typeValue == null || typeValue.trim().length() == 0)
                     && exctx.getAppLog().isWarnEnabled()) {
                 exctx.getAppLog().warn("<send>: type expression \"" + typeexpr
@@ -386,23 +386,23 @@
             typeValue = SCXMLIOProcessor.DEFAULT_EVENT_PROCESSOR;
         }
         Object payload = null;
-        Map<String, Object> payloadDataMap = new LinkedHashMap<String, Object>();
+        Map<String, Object> payloadDataMap = new LinkedHashMap<>();
         addNamelistDataToPayload(exctx, payloadDataMap);
         addParamsToPayload(exctx, payloadDataMap);
         if (!payloadDataMap.isEmpty()) {
-            payload = makeEventPayload(eval, payloadDataMap);
+            payload = payloadDataMap;
         }
         else if (content != null) {
             if (content.getExpr() != null) {
-                payload = clonePayloadValue(eval.eval(ctx, content.getExpr()));
+                payload = eval.cloneData(eval.eval(ctx, content.getExpr()));
             } else {
-                payload = clonePayloadValue(content.getBody());
+                payload = eval.cloneData(content.getBody());
             }
         }
         long wait = 0L;
         String delayString = delay;
         if (delayString == null && delayexpr != null) {
-            Object delayValue = getTextContentIfNodeResult(eval.eval(ctx, delayexpr));
+            Object delayValue = eval.eval(ctx, delayexpr);
             if (delayValue != null) {
                 delayString = delayValue.toString();
             }
@@ -412,7 +412,7 @@
         }
         String eventValue = event;
         if (eventValue == null && eventexpr != null) {
-            eventValue = (String) getTextContentIfNodeResult(eval.eval(ctx, eventexpr));
+            eventValue = (String)eval.eval(ctx, eventexpr);
             if ((eventValue == null)) {
                 throw new SCXMLExpressionException("<send>: event expression \"" + eventexpr
                         + "\" evaluated to null");
diff --git a/src/site/xdoc/guide/contexts-evaluators.xml b/src/site/xdoc/guide/contexts-evaluators.xml
index 93b8458..ca235ac 100644
--- a/src/site/xdoc/guide/contexts-evaluators.xml
+++ b/src/site/xdoc/guide/contexts-evaluators.xml
@@ -110,13 +110,6 @@
         relevant root context and evaluator tuple to use.</p>
     </subsection>
 
-    <subsection name="XPath">
-      <p>See
-        <a href="../apidocs/org/apache/commons/scxml2/env/xpath/package-summary.html">
-          org.apache.commons.scxml2.env.xpath package summary</a> for the
-        relevant root context and evaluator tuple to use.</p>
-    </subsection>
-
     <subsection name="Groovy">
     <p>See
     <a href="../apidocs/org/apache/commons/scxml2/env/groovy/package-summary.html">
diff --git a/src/test/java/org/apache/commons/scxml2/SCXMLTestHelper.java b/src/test/java/org/apache/commons/scxml2/SCXMLTestHelper.java
index 546ac4e..3330cce 100644
--- a/src/test/java/org/apache/commons/scxml2/SCXMLTestHelper.java
+++ b/src/test/java/org/apache/commons/scxml2/SCXMLTestHelper.java
@@ -22,15 +22,12 @@
 import java.io.ObjectInputStream;
 import java.io.ObjectOutputStream;
 import java.io.Reader;
-import java.io.StringReader;
 import java.net.URL;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
 import java.util.Set;
 
-import javax.xml.parsers.DocumentBuilderFactory;
-
 import org.apache.commons.scxml2.env.SimpleDispatcher;
 import org.apache.commons.scxml2.env.Tracer;
 import org.apache.commons.scxml2.io.SCXMLReader;
@@ -40,8 +37,7 @@
 import org.apache.commons.scxml2.model.SCXML;
 import org.apache.commons.scxml2.model.TransitionTarget;
 import org.junit.Assert;
-import org.w3c.dom.Document;
-import org.xml.sax.InputSource;
+
 /**
  * Helper methods for running SCXML unit tests.
  */
@@ -265,22 +261,6 @@
     }
 
     /**
-     * Parses a String containing XML source into a {@link Document}.
-     *
-     * @param xml The XML source as a String.
-     * @return The parsed {@link Document}.
-     */
-    public static Document stringToXMLDocument(final String xml) {
-        try {
-            DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
-            dbf.setNamespaceAware(true);
-            return dbf.newDocumentBuilder().parse(new InputSource(new StringReader(xml)));
-        } catch (Exception e) {
-            throw new RuntimeException("Exception parsing String to Node:\n" + xml);
-        }
-    }
-
-    /**
      * Discourage instantiation.
      */
     private SCXMLTestHelper() {
diff --git a/src/test/java/org/apache/commons/scxml2/env/javascript/JSEvaluatorTest.java b/src/test/java/org/apache/commons/scxml2/env/javascript/JSEvaluatorTest.java
index 2f8b403..dc02916 100644
--- a/src/test/java/org/apache/commons/scxml2/env/javascript/JSEvaluatorTest.java
+++ b/src/test/java/org/apache/commons/scxml2/env/javascript/JSEvaluatorTest.java
@@ -20,10 +20,6 @@
 import java.io.StringReader;
 import java.util.Map;
 
-import javax.xml.xpath.XPath;
-import javax.xml.xpath.XPathConstants;
-import javax.xml.xpath.XPathFactory;
-
 import org.apache.commons.scxml2.Context;
 import org.apache.commons.scxml2.Evaluator;
 import org.apache.commons.scxml2.SCXMLExecutor;
@@ -33,8 +29,6 @@
 import org.junit.Assert;
 import org.junit.Before;
 import org.junit.Test;
-import org.w3c.dom.Element;
-import org.w3c.dom.Node;
 
 /** JUnit 3 test case for the JSEvaluator expression evaluator
  *  class. Includes basic tests for:
diff --git a/src/test/java/org/apache/commons/scxml2/env/xpath/XPathExampleTest.java b/src/test/java/org/apache/commons/scxml2/env/xpath/XPathExampleTest.java
deleted file mode 100644
index 0d40e72..0000000
--- a/src/test/java/org/apache/commons/scxml2/env/xpath/XPathExampleTest.java
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * 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.commons.scxml2.env.xpath;
-
-import java.util.Set;
-
-import org.apache.commons.scxml2.SCXMLExecutor;
-import org.apache.commons.scxml2.SCXMLTestHelper;
-import org.apache.commons.scxml2.TriggerEvent;
-import org.apache.commons.scxml2.model.EnterableState;
-
-import org.junit.Assert;
-import org.junit.Test;
-
-/**
- * SCXML application for the XPath example.
- *
- */
-public class XPathExampleTest {
-
-    @Test
-    public void testExample01Sample() throws Exception {
-
-        SCXMLExecutor exec = SCXMLTestHelper.getExecutor("org/apache/commons/scxml2/env/xpath/example-01.xml");
-        exec.go();
-        Set<EnterableState> currentStates = exec.getStatus().getStates();
-        Assert.assertEquals(1, currentStates.size());
-        Assert.assertEquals("mid", currentStates.iterator().next().getId());
-
-        String payload = "<test xmlns=''><status>complete</status></test>";
-        SCXMLTestHelper.assertPostTriggerState(exec,
-            new TriggerEvent("foo", TriggerEvent.SIGNAL_EVENT,
-                SCXMLTestHelper.stringToXMLDocument(payload)),
-            "end");
-
-    }
-    
-    @Test
-    public void testExample02Sample() throws Exception {
-
-        SCXMLExecutor exec = SCXMLTestHelper.getExecutor("org/apache/commons/scxml2/env/xpath/example-02.xml");
-        exec.go();
-        Set<EnterableState> currentStates = exec.getStatus().getStates();
-        Assert.assertEquals(1, currentStates.size());
-        Assert.assertEquals("end", currentStates.iterator().next().getId());
-
-    }
-}
-
diff --git a/src/test/java/org/apache/commons/scxml2/env/xpath/example-01.xml b/src/test/java/org/apache/commons/scxml2/env/xpath/example-01.xml
deleted file mode 100644
index c5fabd9..0000000
--- a/src/test/java/org/apache/commons/scxml2/env/xpath/example-01.xml
+++ /dev/null
@@ -1,54 +0,0 @@
-<?xml version="1.0"?>
-<!--
-  * 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.
--->
-<!-- SCXML XPath environment: example script -->
-<scxml xmlns="http://www.w3.org/2005/07/scxml"
-       xmlns:cs="http://commons.apache.org/scxml" initial="start" datamodel="xpath"
-       version="1.0">
-
-    <datamodel>
-        <data id="jungle">
-            <animals xmlns="">
-                <lion>
-                    <name>Simba</name>
-                    <age>12</age>
-                </lion>
-                <tiger>
-                    <name>Sher Khan</name>
-                    <age>13</age>
-                </tiger>
-            </animals>
-        </data>
-    </datamodel>
-
-  <state id="start">
-    <onentry>
-      <log label="Lion" expr="string(/jungle/animals/lion/name)" />
-    </onentry>
-    <transition cond="jungle/animals/lion/age = 12" target="mid" />
-  </state>
-
-  <state id="mid">
-    <onentry>
-      <log label="Total age" expr="$jungle/animals/lion/age + jungle/animals/tiger/age" />
-    </onentry>
-    <transition event="foo" cond="$_event/data/test/status = 'complete'" target="end" />
-  </state>
-
-    <final id="end"/>
-
-</scxml>
diff --git a/src/test/java/org/apache/commons/scxml2/env/xpath/example-02.xml b/src/test/java/org/apache/commons/scxml2/env/xpath/example-02.xml
deleted file mode 100644
index ba88686..0000000
--- a/src/test/java/org/apache/commons/scxml2/env/xpath/example-02.xml
+++ /dev/null
@@ -1,41 +0,0 @@
-<?xml version="1.0"?>
-<!--
-  * 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.
--->
-<!-- SCXML XPath environment: example script using XPath with namespaces -->
-<scxml xmlns="http://www.w3.org/2005/07/scxml" initial="start" datamodel="xpath" version="1.0"
-       xmlns:a="http://example.com/a"
-       xmlns:b="http://example.com/b"
-       xmlns:c="http://example.com/c">
-
-    <datamodel>
-        <data id="foo">
-            <bar xmlns="">
-                <a:alpha>1</a:alpha>
-                <b:beta>2</b:beta>
-                <c:gamma>3</c:gamma>
-            </bar>
-        </data>
-    </datamodel>
-
-    <state id="start">
-        <transition cond="$foo/bar/a:alpha + $foo/bar/b:beta = $foo/bar/c:gamma"
-                    target="end" />
-    </state>
-
-    <final id="end"/>
-
-</scxml>
diff --git a/src/test/java/org/apache/commons/scxml2/w3c/W3CTests.java b/src/test/java/org/apache/commons/scxml2/w3c/W3CTests.java
index 2cf6dfd..627bd58 100644
--- a/src/test/java/org/apache/commons/scxml2/w3c/W3CTests.java
+++ b/src/test/java/org/apache/commons/scxml2/w3c/W3CTests.java
@@ -59,7 +59,7 @@
  * To execute one or multiple IRP tests the commandline parameter <b>run</b> must be specified.
  * </p>
  * <p>
- * Optional environment parameter <b>-Ddatamodel=&lt;minimal|ecma|xpath&gt;</b> can be specified to limit the
+ * Optional environment parameter <b>-Ddatamodel=&lt;minimal|ecma&gt;</b> can be specified to limit the
  * execution of the tests for and using only the specified datamodel language.
  * </p>
  * <p>
@@ -80,13 +80,11 @@
     private static final String SCXML_IRP_BASE_URL = "http://www.w3.org/Voice/2013/scxml-irp/";
     private static final String SCXML_IRP_MANIFEST_URI = "manifest.xml";
     private static final String SCXML_IRP_ECMA_XSL_URI = "confEcma.xsl";
-    private static final String SCXML_IRP_XPATH_XSL_URI = "confXpath.xsl";
 
     private static final String TESTS_SRC_DIR = "src/w3c/scxml-irp/";
     private static final String TXML_TESTS_DIR = TESTS_SRC_DIR + "txml/";
     private static final String MINIMAL_TESTS_DIR = TESTS_SRC_DIR + "minimal/";
     private static final String ECMA_TESTS_DIR = TESTS_SRC_DIR + "ecma/";
-    private static final String XPATH_TESTS_DIR = TESTS_SRC_DIR + "xpath/";
     private static final String PACKAGE_PATH = "/"+W3CTests.class.getPackage().getName().replace('.','/');
     private static final String TESTS_FILENAME = PACKAGE_PATH + "/tests.xml";
     private static final String SCXML_IRP_MINIMAL_XSL_FILENAME = PACKAGE_PATH + "/confMinimal.xsl";
@@ -117,10 +115,6 @@
             String minimalStatus;
             @XmlAttribute(name="ecma")
             String ecmaStatus;
-            @XmlAttribute(name="xpath")
-            String xpathStatus;
-            @XmlAttribute
-            Boolean xpathEnabled;
             @XmlValue
             private String comment;
 
@@ -156,14 +150,6 @@
                 return ecmaStatus;
             }
 
-            public String getXpathStatus() {
-                return xpathStatus;
-            }
-
-            public boolean isXPathEnabled() {
-                return xpathEnabled == null || xpathEnabled;
-            }
-
             public String getComment() {
                 return comment;
             }
@@ -180,7 +166,7 @@
 
         public LinkedHashMap<String, Test> getTests() {
             if (testsMap == null) {
-                testsMap = new LinkedHashMap<String, Test>();
+                testsMap = new LinkedHashMap<>();
                 if (tests != null) {
                     for (Test t : tests) {
                         testsMap.put(t.getId(), t);
@@ -192,13 +178,12 @@
     }
 
     /**
-     * Datamodel enum representing the minimal, ecma and xpath datamodel types used and tested by the W3C IRP tests.
+     * Datamodel enum representing the minimal and ecma datamodel types used and tested by the W3C IRP tests.
      */
     protected enum Datamodel {
 
         MINIMAL("minimal"),
-        ECMA("ecma"),
-        XPATH("xpath");
+        ECMA("ecma");
 
         private final String value;
 
@@ -263,9 +248,6 @@
                 else if ("#ecma-profile".equals(specid)) {
                     return Datamodel.ECMA;
                 }
-                else if ("#xpath-profile".equals(specid)) {
-                    return Datamodel.XPATH;
-                }
                 return null;
             }
 
@@ -348,7 +330,7 @@
 
         public LinkedHashMap<String, Assertion> getAssertions() {
             if (assertionsMap == null) {
-                assertionsMap = new LinkedHashMap<String, Assertion>();
+                assertionsMap = new LinkedHashMap<>();
                 if (assertions != null) {
                     for (Assertion a : assertions) {
                         assertionsMap.put(a.getId(), a);
@@ -370,9 +352,7 @@
         int minimalFailed;
         int ecmaPassed;
         int ecmaFailed;
-        int xpathPassed;
-        int xpathFailed;
-        ArrayList<String> failedTests = new ArrayList<String>();
+        ArrayList<String> failedTests = new ArrayList<>();
     }
 
     /**
@@ -409,11 +389,11 @@
                 "  make - make previously downloaded  W3C IRP tests by transforming the .txml templates\n" +
                 "  run  - runs test(s), optionally only for a specific datamodel (default: all)\n\n" +
                 "To run a single test, specify -Dtest=<testId>, otherwise all enabled tests will be run.\n" +
-                "To only run test(s) for a specific datamodel, specify -Ddatamodel=<minimal|ecma|xpath>.\n");
+                "To only run test(s) for a specific datamodel, specify -Ddatamodel=<minimal|ecma>.\n");
     }
 
     /**
-     * Downloads the W3C IRP manifest.xml, the IRP ecma and xpath stylesheets to transform the tests, and the
+     * Downloads the W3C IRP manifest.xml, the IRP ecma stylesheet to transform the tests, and the
      * actual test templates (.txml) as defined in the manifest.xml
      * @throws Exception
      */
@@ -425,13 +405,10 @@
         new File(TXML_TESTS_DIR).mkdirs();
         new File(MINIMAL_TESTS_DIR).mkdirs();
         new File(ECMA_TESTS_DIR).mkdirs();
-        new File(XPATH_TESTS_DIR).mkdirs();
         System.out.println("Downloading IRP manifest: " + SCXML_IRP_BASE_URL + SCXML_IRP_MANIFEST_URI);
         FileUtils.copyURLToFile(new URL(SCXML_IRP_BASE_URL + SCXML_IRP_MANIFEST_URI), new File(testsSrcDir, SCXML_IRP_MANIFEST_URI));
         System.out.println("Downloading ecma stylesheet: " + SCXML_IRP_BASE_URL + SCXML_IRP_ECMA_XSL_URI);
         FileUtils.copyURLToFile(new URL(SCXML_IRP_BASE_URL + SCXML_IRP_ECMA_XSL_URI), new File(testsSrcDir, SCXML_IRP_ECMA_XSL_URI));
-        System.out.println("Downloading xpath stylesheet: " + SCXML_IRP_BASE_URL + SCXML_IRP_XPATH_XSL_URI);
-        FileUtils.copyURLToFile(new URL(SCXML_IRP_BASE_URL + SCXML_IRP_XPATH_XSL_URI), new File(testsSrcDir, SCXML_IRP_XPATH_XSL_URI));
         Assertions assertions = loadAssertions();
         for (Assertions.Assertion entry : assertions.getAssertions().values()) {
             for (Assertions.TestCase test : entry.getTestCases()) {
@@ -456,13 +433,12 @@
         TransformerFactory factory = TransformerFactory.newInstance("net.sf.saxon.TransformerFactoryImpl",null);
         factory.setFeature("http://saxon.sf.net/feature/suppressXsltNamespaceCheck", true);
         Transformer ecmaTransformer = factory.newTransformer(new StreamSource(new FileInputStream(new File(testsSrcDir, SCXML_IRP_ECMA_XSL_URI))));
-        Transformer xpathTransformer = factory.newTransformer(new StreamSource(new FileInputStream(new File(testsSrcDir, SCXML_IRP_XPATH_XSL_URI))));
         Transformer minimalTransformer = factory.newTransformer(new StreamSource(getClass().getResourceAsStream(SCXML_IRP_MINIMAL_XSL_FILENAME)));
         Assertions assertions = loadAssertions();
         for (Assertions.Assertion entry : assertions.getAssertions().values()) {
             for (Assertions.TestCase test : entry.getTestCases()) {
                 for (Assertions.Resource resource : test.getResources()) {
-                    processResource(entry.getSpecId(), resource, minimalTransformer, ecmaTransformer, xpathTransformer);
+                    processResource(entry.getSpecId(), resource, minimalTransformer, ecmaTransformer);
                 }
             }
         }
@@ -486,12 +462,10 @@
      * @param resource The test resource definition
      * @param minimalTransformer transformer to produce an minimal datamodel SCXML document from the txml resource
      * @param ecmaTransformer transformer to produce an ecmascript datamodel SCXML document from the txml resource
-     * @param xpathTransformer transformer to produce a xpath datamodel based SCXML document from the txml resource
      * @throws Exception
      */
     protected void processResource(final String specid, final Assertions.Resource resource,
-                                   final Transformer minimalTransformer, final Transformer ecmaTransformer,
-                                   final Transformer xpathTransformer)
+                                   final Transformer minimalTransformer, final Transformer ecmaTransformer)
             throws Exception {
         System.out.println("processing IRP test file " + resource.getFilename());
         FileUtils.copyURLToFile(new URL(SCXML_IRP_BASE_URL + resource.getUri()), new File(TXML_TESTS_DIR + resource.getFilename()));
@@ -501,12 +475,8 @@
         else if (specid.equals("#ecma-profile")) {
             transformResource(resource, ecmaTransformer, ECMA_TESTS_DIR);
         }
-        else if (specid.equals("#xpath-profile")) {
-            transformResource(resource, xpathTransformer, XPATH_TESTS_DIR);
-        }
         else {
             transformResource(resource, ecmaTransformer, ECMA_TESTS_DIR);
-            transformResource(resource, xpathTransformer, XPATH_TESTS_DIR);
         }
     }
 
@@ -575,10 +545,6 @@
             System.out.println(
                     "    ecma    datamodel: "+results.ecmaPassed+" passed,  "+results.ecmaFailed+" failed");
         }
-        if (results.xpathPassed+results.xpathFailed > 0) {
-            System.out.println(
-                    "    xpath   datamodel: "+results.xpathPassed+" passed,  "+results.xpathFailed+" failed");
-        }
         System.out.print("\n");
         if (!results.failedTests.isEmpty()) {
             System.out.println("  failed tests: ");
@@ -643,18 +609,6 @@
                                         results.ecmaFailed++;
                                     }
                                     break;
-                                case XPATH:
-                                    if (test.isXPathEnabled()) {
-                                        skipped = false;
-                                        if (runTests(assertion, testCase, test, XPATH_TESTS_DIR, results.failedTests)) {
-                                            results.xpathPassed++;
-                                        }
-                                        else {
-                                            passed = false;
-                                            results.xpathFailed++;
-                                        }
-                                    }
-                                    break;
                             }
                         }
                         else {
@@ -666,15 +620,6 @@
                                 passed = false;
                                 results.ecmaFailed++;
                             }
-                            if (test.isXPathEnabled()) {
-                                if (runTests(assertion, testCase, test, XPATH_TESTS_DIR, results.failedTests)) {
-                                    results.xpathPassed++;
-                                }
-                                else {
-                                    passed = false;
-                                    results.xpathFailed++;
-                                }
-                            }
                         }
                     }
                 }