Index: XmlTools2/trunk/main.cpp
===================================================================
--- XmlTools2/trunk/main.cpp	(revision 910)
+++ XmlTools2/trunk/main.cpp	(revision 920)
@@ -12,9 +12,11 @@
     parser.setApplicationDescription("Additional documentation can be found at: http://wiki.oni2.net/XmlTools");
 
+    XmlTools *myXmlTools;
     QString filesWildCard, patchFilesWildCard, forceTargetFilesWildcard;
     QString currentVal, newVal, diffOldNewVal, positions;
+    QString xPathExpression;
     XmlFilter filters; // Filters
+
     bool noBackups=false;
-
 
     QCommandLineOption addValuesOption(QStringList() << "a" << "add-values", "Add values to a set of XML elements.");
@@ -26,5 +28,5 @@
 
     QCommandLineOption currentValOption(QStringList() << "c" << "current-val", "Current value(s) [use space as separator].","current-val");
-    QCommandLineOption newValOption(QStringList() << "n" << "new-val", "New value(s) [use space as separator]","new-val.");
+    QCommandLineOption newValOption(QStringList() << "n" << "new-val", "New value(s) [use space as separator].","new-val");
     QCommandLineOption diffOldNewValueOption(QStringList() << "d" << "diff-old-new-val", "Difference between old and new value.","diff-old-new-val");
     QCommandLineOption positionsValueOption(QStringList() << "positions", "Positions [use space as separator] [0-index based].","positions");
@@ -37,4 +39,5 @@
     QCommandLineOption attributeNameOption("attribute-name", "Attribute name of <element-name>  [used as filter].", "attribute-name");
     QCommandLineOption attributeValueOption("attribute-value", "Attribute value of <attribute-name>  [used as filter].", "attribute-value");
+    QCommandLineOption xPathExpressionOption(QStringList() << "x" << "xpath-expression", "XPath 1.0 expression to select elements where processing will occur.", "xpath-expression");
     QCommandLineOption noBackupsOption(QStringList()  << "no-backups", "No backups [faster processing].");
 
@@ -58,4 +61,5 @@
     parser.addOption(attributeNameOption);
     parser.addOption(attributeValueOption);
+    parser.addOption(xPathExpressionOption);
     parser.addOption(noBackupsOption);
 
@@ -71,5 +75,5 @@
     }
 
-    // Check if the user doesn't want backups (it boost XmlTools peformance, lower disk output)
+    // Check if the user doesn't want backups (it boosts XmlTools peformance, lower disk output)
     if(parser.isSet(noBackupsOption)){
         noBackups=true;
@@ -94,4 +98,11 @@
     }
 
+    if(!parser.isSet(elementNameOption) && !parser.isSet(xPathExpressionOption)){
+        UtilXmlTools::displayErrorMessage("Parameter Parsing","element-name option or xpath-expression option is required if not using patch-files option.");
+    }
+    else if(parser.isSet(elementNameOption) && parser.isSet(xPathExpressionOption)){
+        UtilXmlTools::displayErrorMessage("Parameter Parsing","element-name option and xpath-expression options cannot be used simultaneously.");
+    }
+
     // Get element name if available
     if(parser.isSet(elementNameOption)){
@@ -99,6 +110,7 @@
     }
 
-    if(filters.getElementName()==""){
-        UtilXmlTools::displayErrorMessage("Parameter Parsing","element-name option is required if not using patch-files option.");
+    // Get xpath expression if available
+    if(parser.isSet(xPathExpressionOption)){
+        xPathExpression=parser.value(xPathExpressionOption);
     }
 
@@ -155,5 +167,10 @@
     }
 
-    XmlTools myXmlTools(filesWildCard,filters,noBackups);
+    if(parser.isSet(elementNameOption)){
+        myXmlTools=new XmlTools(filesWildCard,filters,noBackups);
+    }
+    else{
+        myXmlTools=new XmlTools(filesWildCard,xPathExpression,noBackups);
+    }
 
 
@@ -165,5 +182,5 @@
         }
 
-        myXmlTools.addValues(newVal);
+        myXmlTools->addValues(newVal);
     }
     else if(parser.isSet(removeValuesOption)){ // Or remove-values option?
@@ -173,5 +190,5 @@
         }
 
-        myXmlTools.removeValues(currentVal);
+        myXmlTools->removeValues(currentVal);
     }
     else if(parser.isSet(replaceValueOption)){ // Or replace-value option?
@@ -181,5 +198,5 @@
         }
 
-        myXmlTools.replaceValue(currentVal,newVal);
+        myXmlTools->replaceValue(currentVal,newVal);
     }
     else if(parser.isSet(replaceAllValuesOption)){ // Or replace-all-values option?
@@ -190,5 +207,5 @@
         }
 
-        myXmlTools.replaceAll(newVal,positions);
+        myXmlTools->replaceAll(newVal,positions);
     }
     else if(parser.isSet(updateElementsOption)){ // Or update-elements option?
@@ -199,8 +216,8 @@
         }
 
-        myXmlTools.updateElements(diffOldNewVal);
+        myXmlTools->updateElements(diffOldNewVal);
     }
     else if(parser.isSet(invertElementsOption)){ // Or invert-elements option?
-        myXmlTools.invertElements();
+        myXmlTools->invertElements();
     }
     else{
@@ -209,4 +226,5 @@
     }
 
+    //delete myXmlTools;
     //std::cout << "Started" << std::endl;
 
Index: XmlTools2/trunk/readme.txt
===================================================================
--- XmlTools2/trunk/readme.txt	(revision 910)
+++ XmlTools2/trunk/readme.txt	(revision 920)
@@ -35,4 +35,6 @@
 
 -Remove XML from existing files (patch only).
+
+-Select elements using element name, parent element name, attribute name/value and XPath 1.0.
 
 -Powerful custom XML editing using javascript (for what you can't do with native operations) (patch only). 
@@ -75,2 +77,4 @@
 REMOVE -> REMOVE_NODE
 CUSTOMCODE -> CUSTOM_CODE
+-Added option to select xml elements by attribute name and value
+-Added option to select xml elements by XPath 1.0 (should reduce the need of javascript)
Index: XmlTools2/trunk/util.cpp
===================================================================
--- XmlTools2/trunk/util.cpp	(revision 910)
+++ XmlTools2/trunk/util.cpp	(revision 920)
@@ -3,4 +3,9 @@
 namespace GlobalVars{
 QString AppName="XmlTools";
+#ifdef Q_OS_WIN
+QString AppExecutable=AppName+".exe";
+#else
+QString AppExecutable="./"+AppName; // Mac OS needs unix like executing
+#endif
 QString AppVersion="2.0";
 }
Index: XmlTools2/trunk/util.h
===================================================================
--- XmlTools2/trunk/util.h	(revision 910)
+++ XmlTools2/trunk/util.h	(revision 920)
@@ -10,4 +10,5 @@
 namespace GlobalVars{
 extern QString AppName;
+extern QString AppExecutable;
 extern QString AppVersion;
 }
Index: XmlTools2/trunk/utilxmltools.cpp
===================================================================
--- XmlTools2/trunk/utilxmltools.cpp	(revision 910)
+++ XmlTools2/trunk/utilxmltools.cpp	(revision 920)
@@ -55,4 +55,49 @@
 }
 
+void getAllXpathElements(const QString &xPathExpression, pugi::xml_document &doc, QList<pugi::xml_node> &result){
+
+    pugi::xpath_node_set selectedNodes;
+    pugi::xpath_node node;
+
+    try
+    {
+        selectedNodes = doc.select_nodes(xPathExpression.toLatin1().constData());
+    }
+
+    catch (const pugi::xpath_exception& e)
+    {
+        displayErrorMessage("XPath element selection","Selection of elements using the XPathExpression: '" + xPathExpression + "' failed:\n" + e.what());
+    }
+
+    for (pugi::xpath_node_set::const_iterator currNode = selectedNodes.begin(); currNode != selectedNodes.end(); ++currNode)
+    {
+        node = *currNode;
+        if(node){ // if node != null
+            result << node.node();
+        }
+    }
+
+    if(result.isEmpty()){
+        result << pugi::xml_node(); // add an empty node if none found
+    }
+
+}
+
+pugi::xml_node getFirstXpathElement(const QString &xPathExpression, pugi::xml_document &doc){
+    pugi::xpath_node selectedNode;
+
+    try
+    {
+        selectedNode = doc.select_single_node(xPathExpression.toLatin1().constData());
+    }
+
+    catch (const pugi::xpath_exception& e)
+    {
+        displayErrorMessage("XPath element selection","Selection of element using the XPathExpression: '" + xPathExpression + "' failed:\n" + e.what());
+    }
+
+    return selectedNode.node();
+}
+
 void getAllNamedElements(pugi::xml_node &node, QList<pugi::xml_node> &result, XmlFilter &filters){
     for (pugi::xml_node_iterator currNode = node.begin(); currNode != node.end(); ++currNode)
@@ -70,5 +115,5 @@
 }
 
-pugi::xml_node getFirstNamedElements(pugi::xml_node &node, XmlFilter &filters){
+pugi::xml_node getFirstNamedElement(pugi::xml_node &node, XmlFilter &filters){
 
     pugi::xml_node foundNode;
@@ -82,5 +127,5 @@
         }
 
-        foundNode=getFirstNamedElements(*currNode,filters);
+        foundNode=getFirstNamedElement(*currNode,filters);
 
         if(foundNode.type()!=pugi::node_null){
Index: XmlTools2/trunk/utilxmltools.h
===================================================================
--- XmlTools2/trunk/utilxmltools.h	(revision 910)
+++ XmlTools2/trunk/utilxmltools.h	(revision 920)
@@ -14,7 +14,9 @@
 void backupFile(const QString &file);
 void getAllNamedElements(pugi::xml_node &node, QList<pugi::xml_node> &result, XmlFilter &filters);
+void getAllXpathElements(const QString &xPathExpression, pugi::xml_document &doc, QList<pugi::xml_node> &result);
 void displaySuccessMessage(const int numberOperations, const QString &operation);
 void displayErrorMessage(const QString& operation, const QString &message, bool exitProgram=true);
-pugi::xml_node getFirstNamedElements(pugi::xml_node &node, XmlFilter &filters);
+pugi::xml_node getFirstNamedElement(pugi::xml_node &node, XmlFilter &filters);
+pugi::xml_node getFirstXpathElement(const QString &xPathExpression, pugi::xml_document &doc);
 
 //// inline functions
Index: XmlTools2/trunk/xmlfilter.cpp
===================================================================
--- XmlTools2/trunk/xmlfilter.cpp	(revision 910)
+++ XmlTools2/trunk/xmlfilter.cpp	(revision 920)
@@ -46,2 +46,10 @@
     this->attributeValue=attributeValue;
 }
+
+// Clears filter
+void XmlFilter::clear(){
+    this->elementName.clear();
+    this->parentElementName.clear();
+    this->attributeName.clear();
+    this->attributeValue.clear();
+}
Index: XmlTools2/trunk/xmlfilter.h
===================================================================
--- XmlTools2/trunk/xmlfilter.h	(revision 910)
+++ XmlTools2/trunk/xmlfilter.h	(revision 920)
@@ -21,4 +21,6 @@
     void setAttributeName(QString attributeName);
     void setAttributeValue(QString attributeValue);
+
+    void clear();
 private:
     QString elementName;
Index: XmlTools2/trunk/xmlpatch.cpp
===================================================================
--- XmlTools2/trunk/xmlpatch.cpp	(revision 910)
+++ XmlTools2/trunk/xmlpatch.cpp	(revision 920)
@@ -44,8 +44,8 @@
 }
 
-void XmlPatch::addToOperation(const QString &xmlString, XmlFilter &filters, const QString &filesWildcard){
+void XmlPatch::insertNodesOperation(const QString &xmlString, XmlFilter &filters, const QString &xPathExpression, const QString &filesWildcard){
 
     QStringList filesToProcess;
-    pugi::xml_node nodeToInsertion;
+    QList<pugi::xml_node> nodesToInsertion;
     pugi::xml_document newNode;
     pugi::xml_parse_result result;
@@ -54,5 +54,5 @@
 
     if(filesToProcess.isEmpty()){
-        UtilXmlTools::displayErrorMessage("@ADD_INSIDE_NODE","No XML files were found for the wildcard: "+filesWildcard);
+        UtilXmlTools::displayErrorMessage("@ADD_INSIDE_NODES","No XML files were found for the wildcard: "+filesWildcard);
     }
 
@@ -60,5 +60,5 @@
 
     if(result.status!=pugi::status_ok){
-        UtilXmlTools::displayErrorMessage("@ADD_INSIDE_NODE", "The xml node to insert is invalid.\n" + Util::toQString(result.description()));
+        UtilXmlTools::displayErrorMessage("@ADD_INSIDE_NODES", "The xml node to insert is invalid.\n" + Util::toQString(result.description()));
     }
 
@@ -66,42 +66,55 @@
     for(int i=0; i<filesToProcess.size(); i++){
 
-        UtilXmlTools::loadXmlFile(filesToProcess[i],this->document,this->rootNode,this->backupsEnabled,"@ADD_INSIDE_NODE");
-
-        nodeToInsertion=UtilXmlTools::getFirstNamedElements(this->rootNode,filters);
-
-        if(nodeToInsertion.type()==pugi::node_null){
+        UtilXmlTools::loadXmlFile(filesToProcess[i],this->document,this->rootNode,this->backupsEnabled,"@ADD_INSIDE_NODES");
+
+        // Check how the element will be fetched via element name or xpath expression
+        if(xPathExpression.isEmpty()){
+            UtilXmlTools::getAllNamedElements(this->rootNode,nodesToInsertion,filters);
+        }
+        else{
+            UtilXmlTools::getAllXpathElements(xPathExpression,this->document,nodesToInsertion);
+        }
+
+        if(nodesToInsertion[0].type()==pugi::node_null){
 
             QString errMessage;
 
-            errMessage = "It wasn't found a node with a ElementName: '" + filters.getElementName() + "'";
-            if(filters.getParentElementName()!=""){
-                errMessage += " and a ParentElementName: '" + filters.getParentElementName() + "'";
-            }
-            if(filters.getAttributeName()!=""){
-                errMessage += " and an AttributeName: '" + filters.getAttributeName() + "' and an AttributeValue: '" + filters.getAttributeValue() + "'";
-            }
-
-            UtilXmlTools::displayErrorMessage("@ADD_INSIDE_NODE",errMessage);
-        }
-
-        nodeToInsertion.prepend_copy(newNode.first_child()); // append the new node
-
-
-        UtilXmlTools::saveXmlFile(filesToProcess[i],this->document, "@ADD_INSIDE_NODE");
-    }
-
-    UtilXmlTools::displaySuccessMessage(filesToProcess.size(),"@ADD_INSIDE_NODE");
-}
-
-void XmlPatch::removeNodeOperation(XmlFilter &filters, const QString &filesWildcard){
+            if(xPathExpression.isEmpty()){
+                errMessage = "It wasn't found any node with a ElementName: '" + filters.getElementName() + "'";
+                if(filters.getParentElementName()!=""){
+                    errMessage += " and a ParentElementName: '" + filters.getParentElementName() + "'";
+                }
+                if(filters.getAttributeName()!=""){
+                    errMessage += " and an AttributeName: '" + filters.getAttributeName() + "' and an AttributeValue: '" + filters.getAttributeValue() + "'";
+                }
+            }
+            else{
+                errMessage = "It wasn't found any node with a XPathExpression: '" + xPathExpression + "'";
+            }
+
+            UtilXmlTools::displayErrorMessage("@ADD_INSIDE_NODES",errMessage);
+        }
+
+        for(int j=0; j<nodesToInsertion.size(); j++){
+            nodesToInsertion[j].prepend_copy(newNode.first_child()); // append the new node
+        }
+
+
+        UtilXmlTools::saveXmlFile(filesToProcess[i],this->document, "@ADD_INSIDE_NODES");
+    }
+
+    UtilXmlTools::displaySuccessMessage(filesToProcess.size(),"@ADD_INSIDE_NODES");
+}
+
+void XmlPatch::removeNodesOperation(XmlFilter &filters, const QString &xPathExpression, const QString &filesWildcard){
 
     QStringList filesToProcess;
 
-    pugi::xml_node nodeToDeletion;
+    QList<pugi::xml_node> nodesToDeletion;
 
     filesToProcess=UtilXmlTools::getAllXmlFilesByWildcard(filesWildcard);
 
     if(filesToProcess.isEmpty()){
-        UtilXmlTools::displayErrorMessage("@REMOVE_NODE","No XML files were found for the wildcard: "+filesWildcard);
+        UtilXmlTools::displayErrorMessage("@REMOVE_NODES","No XML files were found for the wildcard: "+filesWildcard);
     }
 
@@ -109,39 +122,58 @@
     for(int i=0; i<filesToProcess.size(); i++){
 
-        UtilXmlTools::loadXmlFile(filesToProcess[i],this->document,this->rootNode,this->backupsEnabled,"@REMOVE_NODE");
-
-        nodeToDeletion=UtilXmlTools::getFirstNamedElements(this->rootNode,filters);
-
-        if(nodeToDeletion.type()==pugi::node_null){
+        UtilXmlTools::loadXmlFile(filesToProcess[i],this->document,this->rootNode,this->backupsEnabled,"@REMOVE_NODES");
+
+        // Check how the element will be fetched via element name or xpath expression
+        if(xPathExpression.isEmpty()){
+            UtilXmlTools::getAllNamedElements(this->rootNode,nodesToDeletion,filters);
+        }
+        else{
+            UtilXmlTools::getAllXpathElements(xPathExpression,this->document,nodesToDeletion);
+        }
+
+        if(nodesToDeletion[0].type()==pugi::node_null){
+
             QString errMessage;
 
-            errMessage = "It wasn't found a node with a ElementName: '" + filters.getElementName() + "'";
-            if(filters.getParentElementName()!=""){
-                errMessage += " and a ParentElementName: '" + filters.getParentElementName() + "'";
-            }
-            if(filters.getAttributeName()!=""){
-                errMessage += " and an AttributeName: '" + filters.getAttributeName() + "' and an AttributeValue: '" + filters.getAttributeValue() + "'";
-            }
-
-            UtilXmlTools::displayErrorMessage("@REMOVE_NODE",errMessage);
-        }
-
-        if(!nodeToDeletion.parent().remove_child(nodeToDeletion)){  // remove the node
-
-            QString errMessage;
-
-            errMessage = "Couldn't remove the node with Element '" + filters.getElementName() + "'";
-
-            if(filters.getParentElementName()!=""){
-                errMessage += " and a ParentElement: '" + filters.getParentElementName() + "'";
-            }
-
-            UtilXmlTools::displayErrorMessage("@REMOVE_NODE",errMessage);
-        }
-
-        UtilXmlTools::saveXmlFile(filesToProcess[i],this->document, "@REMOVE_NODE");
-    }
-
-    UtilXmlTools::displaySuccessMessage(filesToProcess.size(), "@REMOVE_NODE");
+            if(xPathExpression.isEmpty()){
+                errMessage = "It wasn't found any node with a ElementName: '" + filters.getElementName() + "'";
+                if(filters.getParentElementName()!=""){
+                    errMessage += " and a ParentElementName: '" + filters.getParentElementName() + "'";
+                }
+                if(filters.getAttributeName()!=""){
+                    errMessage += " and an AttributeName: '" + filters.getAttributeName() + "' and an AttributeValue: '" + filters.getAttributeValue() + "'";
+                }
+            }
+            else{
+                errMessage = "It wasn't found any node with a XPathExpression: '" + xPathExpression + "'";
+            }
+
+            UtilXmlTools::displayErrorMessage("@REMOVE_NODES",errMessage);
+        }
+
+        // Delete all the specified nodes
+        for(int j=0; j<nodesToDeletion.size(); j++){
+            if(!nodesToDeletion[j].parent().remove_child(nodesToDeletion[j])){  // remove the node
+
+                QString errMessage;
+                if(xPathExpression.isEmpty()){
+                    errMessage = "Couldn't remove the node with Element '" + filters.getElementName() + "'";
+
+                    if(filters.getParentElementName()!=""){
+                        errMessage += " and a ParentElement: '" + filters.getParentElementName() + "'";
+                    }
+                }
+                else{
+                    errMessage = "Couldn't remove the node with the XPathExpression '" + xPathExpression + "'";
+                }
+
+                UtilXmlTools::displayErrorMessage("@REMOVE_NODES",errMessage);
+            }
+        }
+
+        UtilXmlTools::saveXmlFile(filesToProcess[i],this->document, "@REMOVE_NODES");
+    }
+
+    UtilXmlTools::displaySuccessMessage(filesToProcess.size(), "@REMOVE_NODES");
 }
 
@@ -152,9 +184,9 @@
 
     // Avoid infinite fork loops
-    if(commandString.contains("-p") || commandString.contains("--patch-files")){
+    if(commandString.contains(" -p ") || commandString.contains(" --patch-files ")){
         UtilXmlTools::displayErrorMessage("@COMMAND","Use of --patch-files option is not allowed inside a patch file");
     }
 
-    newXmlToolsInstance.start(GlobalVars::AppName + " " + commandString);
+    newXmlToolsInstance.start(GlobalVars::AppExecutable + " " + commandString);
     newXmlToolsInstance.waitForFinished(-1); // wait for new instance to finish
 
@@ -166,5 +198,9 @@
     }
 
-    std::cout << "@COMMAND patch operation output:\n" << resultOutput.toLatin1().constData() << std::endl;
+    std::cout << "@COMMAND patch operation output:\n"
+              << "########################################################################\n"
+              << resultOutput.toLatin1().constData()
+              << "########################################################################"
+              << std::endl;
 
     UtilXmlTools::displaySuccessMessage(1,"@COMMAND");
@@ -289,4 +325,5 @@
     QString line, filesWildcard;
     QString xmlToInsert, command, jsCode;
+    QString xPathExpression;
     XmlFilter filters;
 
@@ -298,5 +335,6 @@
             continue;
         }
-        else if(line.startsWith("@ADD_INSIDE_NODE")){
+        else if(line.startsWith("@ADD_INSIDE_NODES")){
+            xPathExpression=getPatchParameterValue(line,"XPathExpression");
             filters.setElementName(getPatchParameterValue(line,"ElementName"));
             filters.setParentElementName(getPatchParameterValue(line,"ParentElementName"));
@@ -311,11 +349,17 @@
             }
 
-            // Check attribute filters
+            // Check options
+            if(xPathExpression.isEmpty() && filters.getElementName().isEmpty()){
+                UtilXmlTools::displayErrorMessage("@ADD_INSIDE_NODES","ElementName option or XPathExpression option is required.");
+            }
+            else if(!xPathExpression.isEmpty() && !filters.getElementName().isEmpty()){
+                UtilXmlTools::displayErrorMessage("@ADD_INSIDE_NODES","ElementName option and XPathExpression options cannot be used simultaneously.");
+            }
             if(filters.getAttributeName()!="" && filters.getAttributeValue()==""){
-                UtilXmlTools::displayErrorMessage("@ADD_INSIDE_NODE","attribute-value option is required if using attribute-name option.");
+                UtilXmlTools::displayErrorMessage("@ADD_INSIDE_NODES","AttributeValue option is required if using AttributeName option.");
             }
 
             if(filters.getAttributeValue()!="" && filters.getAttributeName()==""){
-                UtilXmlTools::displayErrorMessage("@ADD_INSIDE_NODE","attribute-name option is required if using attribute-value option.");
+                UtilXmlTools::displayErrorMessage("@ADD_INSIDE_NODES","AttributeName option is required if using AttributeValue option.");
             }
 
@@ -328,9 +372,14 @@
             }
 
-            addToOperation(xmlToInsert,filters,filesWildcard);
-
-        }
-        else if(line.startsWith("@REMOVE_NODE")){
-
+            insertNodesOperation(xmlToInsert,filters,xPathExpression,filesWildcard);
+
+            xmlToInsert.clear();
+            filters.clear();
+            xPathExpression.clear();
+            filesWildcard.clear();
+        }
+        else if(line.startsWith("@REMOVE_NODES")){
+
+            xPathExpression=getPatchParameterValue(line,"XPathExpression");
             filters.setElementName(getPatchParameterValue(line,"ElementName"));
             filters.setParentElementName(getPatchParameterValue(line,"ParentElementName"));
@@ -345,21 +394,35 @@
             }
 
-            // Check attribute filters
+            // Check options
+            if(xPathExpression.isEmpty() && filters.getElementName().isEmpty()){
+                UtilXmlTools::displayErrorMessage("@REMOVE_NODES","ElementName option or XPathExpression option is required.");
+            }
+            else if(!xPathExpression.isEmpty() && !filters.getElementName().isEmpty()){
+                UtilXmlTools::displayErrorMessage("@REMOVE_NODES","ElementName option and XPathExpression options cannot be used simultaneously.");
+            }
+
             if(filters.getAttributeName()!="" && filters.getAttributeValue()==""){
-                UtilXmlTools::displayErrorMessage("@REMOVE_NODE","attribute-value option is required if using attribute-name option.");
+                UtilXmlTools::displayErrorMessage("@REMOVE_NODES","AttributeValue option is required if using AttributeName option.");
             }
 
             if(filters.getAttributeValue()!="" && filters.getAttributeName()==""){
-                UtilXmlTools::displayErrorMessage("@REMOVE_NODE","attribute-name option is required if using attribute-value option.");
-            }
-
-            removeNodeOperation(filters,filesWildcard);
-
+                UtilXmlTools::displayErrorMessage("@REMOVE_NODES","AttributeName option is required if using AttributeValue option.");
+            }
+
+            removeNodesOperation(filters,xPathExpression,filesWildcard);
+
+            filters.clear();
+            xPathExpression.clear();
+            filesWildcard.clear();
         }
         else if(line.startsWith("@COMMAND")){
 
-            command=getPatchParameterValue(line,"");
+            command=getPatchParameterValue(line,"Arguments");
+
+            command.replace("'","\""); //replace apostrophe by quotes, to avoid problems
 
             executeCommandOperation(command);
+
+            command.clear();
         }
         else if(line.startsWith("@CUSTOM_CODE")){
@@ -382,4 +445,7 @@
 
             executeCustomCommandOperation(jsCode,filesWildcard);
+
+            jsCode.clear();
+            filesWildcard.clear();
         }
     }
@@ -390,8 +456,9 @@
     int startValueIdx, endValueIdx;
 
-    parameter+=" "; // Parameters include a space before it's value.
+    parameter=" "+parameter+" "; // Parameters include a space before and after it's value.
 
     if(!line.contains(parameter)){
-        if(parameter=="ParentElementName " || parameter=="AttributeName " || parameter=="AttributeValue "){
+        if(parameter==" ParentElementName " || parameter==" AttributeName " || parameter==" AttributeValue "
+                || parameter==" ElementName " || parameter==" XPathExpression "){
             return ""; // not mandatory
         }
Index: XmlTools2/trunk/xmlpatch.h
===================================================================
--- XmlTools2/trunk/xmlpatch.h	(revision 910)
+++ XmlTools2/trunk/xmlpatch.h	(revision 920)
@@ -16,6 +16,6 @@
     bool backupsEnabled;
     QString getPatchParameterValue(const QString& line, QString parameter);
-    void addToOperation(const QString &xmlString, XmlFilter &filters, const QString &filesWildcard="");
-    void removeNodeOperation(XmlFilter &filters, const QString &filesWildcard="");
+    void insertNodesOperation(const QString &xmlString, XmlFilter &filters, const QString &xPathExpression, const QString &filesWildcard="");
+    void removeNodesOperation(XmlFilter &filters, const QString &xPathExpression, const QString &filesWildcard="");
     void executeCommandOperation(const QString &commandString);
     void executeCustomCommandOperation(const QString &jsString, const QString &filesWildcard="");
Index: XmlTools2/trunk/xmltools.cpp
===================================================================
--- XmlTools2/trunk/xmltools.cpp	(revision 910)
+++ XmlTools2/trunk/xmltools.cpp	(revision 920)
@@ -1,4 +1,5 @@
 #include "xmltools.h"
 
+// Filters constructor
 XmlTools::XmlTools(QString filesWildcard, XmlFilter filter, bool noBackups)
 {
@@ -12,4 +13,12 @@
 }
 
+// XPath constructor
+XmlTools::XmlTools(QString filesWildcard, QString xPathExpression, bool noBackups)
+{
+    this->filesToProcess=UtilXmlTools::getAllXmlFilesByWildcard(filesWildcard);
+    this->xPathExpression=xPathExpression;
+    this->backupsEnabled=!noBackups;
+}
+
 // Adds new values to an element
 void XmlTools::addValues(QString newValues){
@@ -24,5 +33,12 @@
 
         newValuesList=Util::qStringListFromSpacedString(newValues);
-        UtilXmlTools::getAllNamedElements(this->rootNode,elements,this->filters);
+
+        // Check how the elements will be fetched via element name or xpath expression
+        if(this->xPathExpression==""){
+            UtilXmlTools::getAllNamedElements(this->rootNode,elements,this->filters);
+        }
+        else{
+            UtilXmlTools::getAllXpathElements(this->xPathExpression,this->document,elements);
+        }
 
         for(int j=0; j<elements.size(); j++){
@@ -57,5 +73,11 @@
         UtilXmlTools::loadXmlFile(this->filesToProcess[i],this->document,this->rootNode,this->backupsEnabled, "remove-values");
 
-        UtilXmlTools::getAllNamedElements(this->rootNode,elements,this->filters);
+        // Check how the elements will be fetched via element name or xpath expression
+        if(this->xPathExpression==""){
+            UtilXmlTools::getAllNamedElements(this->rootNode,elements,this->filters);
+        }
+        else{
+            UtilXmlTools::getAllXpathElements(this->xPathExpression,this->document,elements);
+        }
 
         valuesToRemoveList=Util::qStringListFromSpacedString(valuesToRemove);
@@ -98,5 +120,11 @@
         UtilXmlTools::loadXmlFile(this->filesToProcess[i],this->document,this->rootNode,this->backupsEnabled, "replace-value");
 
-        UtilXmlTools::getAllNamedElements(this->rootNode,elements,this->filters);
+        // Check how the elements will be fetched via element name or xpath expression
+        if(this->xPathExpression==""){
+            UtilXmlTools::getAllNamedElements(this->rootNode,elements,this->filters);
+        }
+        else{
+            UtilXmlTools::getAllXpathElements(this->xPathExpression,this->document,elements);
+        }
 
         for(int j=0; j<elements.size(); j++){
@@ -132,5 +160,11 @@
         UtilXmlTools::loadXmlFile(this->filesToProcess[i],this->document,this->rootNode,this->backupsEnabled, "replace-all");
 
-        UtilXmlTools::getAllNamedElements(this->rootNode,elements,this->filters);
+        // Check how the elements will be fetched via element name or xpath expression
+        if(this->xPathExpression==""){
+            UtilXmlTools::getAllNamedElements(this->rootNode,elements,this->filters);
+        }
+        else{
+            UtilXmlTools::getAllXpathElements(this->xPathExpression,this->document,elements);
+        }
 
 
@@ -166,5 +200,11 @@
         UtilXmlTools::loadXmlFile(this->filesToProcess[i],this->document,this->rootNode,this->backupsEnabled, "update-elements");
 
-        UtilXmlTools::getAllNamedElements(this->rootNode,elements,this->filters);
+        // Check how the elements will be fetched via element name or xpath expression
+        if(this->xPathExpression==""){
+            UtilXmlTools::getAllNamedElements(this->rootNode,elements,this->filters);
+        }
+        else{
+            UtilXmlTools::getAllXpathElements(this->xPathExpression,this->document,elements);
+        }
 
 
@@ -207,5 +247,11 @@
         QStringList invertedElements; //Inverting the element order
 
-        UtilXmlTools::getAllNamedElements(this->rootNode,elements,this->filters);
+        // Check how the elements will be fetched via element name or xpath expression
+        if(this->xPathExpression==""){
+            UtilXmlTools::getAllNamedElements(this->rootNode,elements,this->filters);
+        }
+        else{
+            UtilXmlTools::getAllXpathElements(this->xPathExpression,this->document,elements);
+        }
 
         // Read all elements and save to the list
Index: XmlTools2/trunk/xmltools.h
===================================================================
--- XmlTools2/trunk/xmltools.h	(revision 910)
+++ XmlTools2/trunk/xmltools.h	(revision 920)
@@ -26,4 +26,5 @@
 public:
     XmlTools(QString filesWildcard, XmlFilter filter, bool noBackups);
+    XmlTools(QString filesWildcard, QString xPathExpression, bool noBackups);
     void addValues(QString newValues);
     void removeValues(QString valuesToRemove);
@@ -37,4 +38,5 @@
     pugi::xml_node rootNode;
     QStringList filesToProcess;
+    QString xPathExpression;
     XmlFilter filters;
     bool backupsEnabled;
