diff --git a/mysql-test/r/xml.result b/mysql-test/r/xml.result
index b4121ae473d..3ed3df546d1 100644
--- a/mysql-test/r/xml.result
+++ b/mysql-test/r/xml.result
@@ -544,3 +544,5 @@ extractvalue('aB','a|/b')
a
select extractvalue('A','/');
ERROR HY000: XPATH syntax error: '>'
+select extractvalue('bb!','//b!');
+ERROR HY000: XPATH syntax error: '!'
diff --git a/mysql-test/t/xml.test b/mysql-test/t/xml.test
index 0e24692f0fa..e69ab5ee58b 100644
--- a/mysql-test/t/xml.test
+++ b/mysql-test/t/xml.test
@@ -237,3 +237,9 @@ select extractvalue('aB','a|/b');
#
--error 1105
select extractvalue('A','/');
+
+#
+# Bug#16313 XML: extractvalue() ignores '!' in names
+#
+--error 1105
+select extractvalue('bb!','//b!');
diff --git a/sql/item_xmlfunc.cc b/sql/item_xmlfunc.cc
index d86b6acfc56..aad9e12f6c5 100644
--- a/sql/item_xmlfunc.cc
+++ b/sql/item_xmlfunc.cc
@@ -1976,8 +1976,17 @@ static int my_xpath_parse_AndExpr(MY_XPATH *xpath)
*/
static int my_xpath_parse_ne(MY_XPATH *xpath)
{
- return my_xpath_parse_term(xpath, MY_XPATH_LEX_EXCL) &&
- my_xpath_parse_term(xpath, MY_XPATH_LEX_EQ);
+ MY_XPATH_LEX prevtok= xpath->prevtok;
+ if (!my_xpath_parse_term(xpath, MY_XPATH_LEX_EXCL))
+ return 0;
+ if (!my_xpath_parse_term(xpath, MY_XPATH_LEX_EQ))
+ {
+ /* Unget the exclamation mark */
+ xpath->lasttok= xpath->prevtok;
+ xpath->prevtok= prevtok;
+ return 0;
+ }
+ return 1;
}
static int my_xpath_parse_EqualityOperator(MY_XPATH *xpath)
{