diff --git a/exist-core/src/main/antlr/org/exist/xquery/parser/XQueryTree.g b/exist-core/src/main/antlr/org/exist/xquery/parser/XQueryTree.g index 048ee8e7e85..4e706b6b41d 100644 --- a/exist-core/src/main/antlr/org/exist/xquery/parser/XQueryTree.g +++ b/exist-core/src/main/antlr/org/exist/xquery/parser/XQueryTree.g @@ -3664,6 +3664,11 @@ throws PermissionDeniedException, EXistException, XPathException String nsPrefix = attrib.getQName().equals(XMLConstants.XMLNS_ATTRIBUTE) ? "" : QName.extractLocalName(attrib.getQName()); staticContext.declareInScopeNamespace(nsPrefix,attrib.getLiteralValue()); + + if (context.getStaticNamespaces().containsKey(QName.extractLocalName(attrib.getQName())) && + !context.getStaticNamespaces().get(QName.extractLocalName(attrib.getQName())).equals(attrib.getLiteralValue())) { + throw new XPathException(attrib.getLine(), attrib.getColumn(), ErrorCodes.XUDY0023, "Conflicting namespace for prefix " + QName.extractLocalName(attrib.getQName())); + } } catch (final IllegalQNameException iqe) { throw new XPathException(attrib.getLine(), attrib.getColumn(), ErrorCodes.XPST0081, "No namespace defined for prefix " + attrib.getQName()); } diff --git a/exist-core/src/main/java/org/exist/xquery/ErrorCodes.java b/exist-core/src/main/java/org/exist/xquery/ErrorCodes.java index c1f50a28d9c..3589ba6af7c 100644 --- a/exist-core/src/main/java/org/exist/xquery/ErrorCodes.java +++ b/exist-core/src/main/java/org/exist/xquery/ErrorCodes.java @@ -243,6 +243,42 @@ public class ErrorCodes { public static final ErrorCode XTSE0165 = new W3CErrorCode("XTSE0165","It is a static error if the processor is not able to retrieve the resource identified by the URI reference [ in the href attribute of xsl:include or xsl:import] , or if the resource that is retrieved does not contain a stylesheet module conforming to this specification."); + /* New Error Codes https://www.w3.org/TR/xquery-update-30/#id-new-error-codes */ + public static final ErrorCode XUST0001 = new W3CErrorCode("XUST0001", "It is a static error if an updating expression is used where the expression category rules prohibit it."); + public static final ErrorCode XUST0003 = new W3CErrorCode("XUST0003", "It is a static error if a Prolog contains more than one revalidation declaration."); + public static final ErrorCode XUTY0004 = new W3CErrorCode("XUTY0004", "It is a type error if the insertion sequence of an insert expression contains an attribute node following a node that is not an attribute node."); + public static final ErrorCode XUTY0005 = new W3CErrorCode("XUTY0005", "In an insert expression where into, as first into, or as last into is specified, it is a type error if the target expression returns a non-empty result that does not consist of a single element or document node."); + public static final ErrorCode XUTY0006 = new W3CErrorCode("XUTY0006", "In an insert expression where before or after is specified, it is a type error if the target expression returns a non-empty result that does not consist of a single element, text, comment, or processing instruction node."); + public static final ErrorCode XUTY0007 = new W3CErrorCode("XUTY0007", "It is a type error if the target expression of a delete expression does not return a sequence of zero or more nodes."); + public static final ErrorCode XUTY0008 = new W3CErrorCode("XUTY0008", "In a replace expression, it is a type error if the target expression returns a non-empty result that does not consist of a single element, attribute, text, comment, or processing instruction node."); + public static final ErrorCode XUDY0009 = new W3CErrorCode("XUDY0009", "In a replace expression where value of is not specified, it is a dynamic error if the node returned by the target expression does not have a parent."); + public static final ErrorCode XUTY0010 = new W3CErrorCode("XUTY0010", "In a replace expression where value of is not specified and the target is an element, text, comment, or processing instruction node, it is a type error if the replacement sequence does not consist of zero or more element, text, comment, or processing instruction nodes."); + public static final ErrorCode XUTY0011 = new W3CErrorCode("XUTY0011", "In a replace expression where value of is not specified and the target is an attribute node, it is a type error if the replacement sequence does not consist of zero or more attribute nodes."); + public static final ErrorCode XUTY0012 = new W3CErrorCode("XUTY0012", "In a rename expression, it is a type error if the target expression returns a non-empty result that does not consist of a single element, attribute, or processing instruction node."); + public static final ErrorCode XUTY0013 = new W3CErrorCode("XUTY0013", "In a copy modify expression, it is a type error if a source expression in the copy clause does not return a single node."); + public static final ErrorCode XUDY0014 = new W3CErrorCode("XUDY0014", "In a copy modify expression, it is a dynamic error if the modify clause modifies any node that was not created by the copy clause."); + public static final ErrorCode XUDY0015 = new W3CErrorCode("XUDY0015", "It is a dynamic error if any node is the target of more than one rename expression within the same query."); + public static final ErrorCode XUDY0016 = new W3CErrorCode("XUDY0016", "It is a dynamic error if any node is the target of more than one replace expression (without value of being specified) within the same query."); + public static final ErrorCode XUDY0017 = new W3CErrorCode("XUDY0017", "It is a dynamic error if any node is the target of more than one replace value of expression within the same query."); + public static final ErrorCode XUDY0018 = new W3CErrorCode("XUDY0018", "It is a dynamic error if a function that was declared to be external but not updating returns a non-empty pending update list."); + public static final ErrorCode XUDY0021 = new W3CErrorCode("XUDY0021", "It is a dynamic error if the XDM instance that would result from applying all the updates in a query violates any constraint specified in [XQuery and XPath Data Model (XDM) 3.0]. In this case, none of the updates in the query are made effective."); + public static final ErrorCode XUTY0022 = new W3CErrorCode("XUTY0022", "It is a type error if an insert expression specifies the insertion of an attribute node into a document node."); + public static final ErrorCode XUDY0023 = new W3CErrorCode("XUDY0023", "It is a dynamic error if an insert, replace, or rename expression affects an element node by introducing a new namespace binding that conflicts with one of its existing namespace bindings."); + public static final ErrorCode XUDY0024 = new W3CErrorCode("XUDY0024", "It is a dynamic error if the effect of a set of updating expressions is to introduce conflicting namespace bindings into an element node."); + public static final ErrorCode XUDY0025 = new W3CErrorCode("XUDY0025", "(Not currently used.)"); + public static final ErrorCode XUST0026 = new W3CErrorCode("XUST0026", "It is a static error if a revalidation declaration in a Prolog specifies a revalidation mode that is not supported by the current implementation."); + public static final ErrorCode XUDY0027 = new W3CErrorCode("XUDY0027", "It is a dynamic error if the target expression of an insert, replace, or rename expression evaluates to an empty sequence."); + public static final ErrorCode XUDY0029 = new W3CErrorCode("XUDY0029", "In an insert expression where before or after is specified, it is a dynamic error if the node returned by the target expression does not have a parent."); + public static final ErrorCode XUDY0030 = new W3CErrorCode("XUDY0030", "It is a dynamic error if an insert expression specifies the insertion of an attribute node before or after a child of a document node."); + public static final ErrorCode XUDY0031 = new W3CErrorCode("XUDY0031", "It is a dynamic error if multiple calls to fn:put in the same snapshot specify the same URI (after resolution of relative URIs)."); + public static final ErrorCode XUST0032 = new W3CErrorCode("XUST0032", "It is a static error if an %updating or %simple annotation is used on a VarDecl."); + public static final ErrorCode XUST0033 = new W3CErrorCode("XUST0033", "It is a static error to use more than one %updating or %simple annotation in a given annotation set."); + public static final ErrorCode XUST0034 = new W3CErrorCode("XUST0034", "It is a static error to use more than one updating function assertion in the function assertionXQ30 set of a FunctionTest."); + public static final ErrorCode XUDY0037 = new W3CErrorCode("XUDY0037", "It is a dynamic error if the pending update list returned by the modify expression of a CopyModifyExpr or TransformWithExpr contains a upd:put update primitive."); + public static final ErrorCode XUDY0038 = new W3CErrorCode("XUDY0038", "It is a dynamic error if the function returned by the PrimaryExpr of a dynamic function invocation is an updating function, and the dynamic function invocation is not a partial function applicationXQ30."); + public static final ErrorCode FOUP0001 = new W3CErrorCode("FOUP0001", "It is a dynamic error if the first operand of fn:put is not a node of a supported kind."); + public static final ErrorCode FOUP0002 = new W3CErrorCode("FOUP0002", "It is a dynamic error if the second operand of fn:put is not a valid lexical representation of the xs:anyURI type."); + /* eXist specific XQuery and XPath errors * * Codes have the format [EX][XQ|XP][DY|SE|ST][nnnn] diff --git a/exist-core/src/main/java/org/exist/xquery/XQueryContext.java b/exist-core/src/main/java/org/exist/xquery/XQueryContext.java index 8bac2341af5..e768ff52133 100644 --- a/exist-core/src/main/java/org/exist/xquery/XQueryContext.java +++ b/exist-core/src/main/java/org/exist/xquery/XQueryContext.java @@ -3502,6 +3502,10 @@ public interface CleanupTask { void cleanup(final XQueryContext context, final Predicate predicate); } + public Map getStaticNamespaces() { + return staticNamespaces; + } + @Override public void runCleanupTasks(final Predicate predicate) { if (importedContextsCleanupTasksFns != null) { diff --git a/exist-core/src/test/java/xquery/update/UpdateTests.java b/exist-core/src/test/java/xquery/update/UpdateTests.java new file mode 100644 index 00000000000..9ba9c494b86 --- /dev/null +++ b/exist-core/src/test/java/xquery/update/UpdateTests.java @@ -0,0 +1,32 @@ +/* + * eXist-db Open Source Native XML Database + * Copyright (C) 2001 The eXist-db Authors + * + * info@exist-db.org + * http://www.exist-db.org + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ +package xquery.update; + +import org.exist.test.runner.XSuite; +import org.junit.runner.RunWith; + +@RunWith(XSuite.class) +@XSuite.XSuiteFiles({ + "src/test/xquery/update" +}) +public class UpdateTests { +} diff --git a/exist-core/src/test/xquery/update/namespace-binding.xqm b/exist-core/src/test/xquery/update/namespace-binding.xqm new file mode 100644 index 00000000000..f496da360c3 --- /dev/null +++ b/exist-core/src/test/xquery/update/namespace-binding.xqm @@ -0,0 +1,64 @@ +(: + : eXist-db Open Source Native XML Database + : Copyright (C) 2001 The eXist-db Authors + : + : info@exist-db.org + : http://www.exist-db.org + : + : This library is free software; you can redistribute it and/or + : modify it under the terms of the GNU Lesser General Public + : License as published by the Free Software Foundation; either + : version 2.1 of the License, or (at your option) any later version. + : + : This library is distributed in the hope that it will be useful, + : but WITHOUT ANY WARRANTY; without even the implied warranty of + : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + : Lesser General Public License for more details. + : + : You should have received a copy of the GNU Lesser General Public + : License along with this library; if not, write to the Free Software + : Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + :) +xquery version "3.1"; + +module namespace unbt = "http://exist-db.org/xquery/update/namespace-binding-test"; + +import module namespace xmldb = "http://exist-db.org/xquery/xmldb"; + +declare namespace test = "http://exist-db.org/xquery/xqsuite"; +declare namespace myns = "http://www.foo.com"; + +declare %private variable $unbt:test := document { + + + +}; + +declare + %test:setup +function unbt:setup() { + let $xml := fn:parse-xml('') + return + xmldb:store("/db", "namespace-binding-test-1.xml", $xml) + , + xmldb:store("/db", "namespace-binding-test-2.xml", $unbt:test) +}; + +declare + %test:teardown +function unbt:teardown() { + xmldb:remove("/db/namespace-binding-test-1.xml"), + xmldb:remove("/db/namespace-binding-test-2.xml"), +}; + +declare + %test:assertError("XUDY0023") +function unbt:insert-namespaced-attribute-1() { + update insert attribute myns:baz { "qux" } into doc("/db/namespace-binding-test-1.xml")/x/z +}; + +declare + %test:assertError("XUDY0023") +function unbt:insert-namespaced-attribute-2() { + update insert attribute myns:baz { "qux" } into doc("/db/namespace-binding-test-2.xml")/x/z +};