diff --git a/exist-core/src/main/java/org/exist/xquery/DynamicNameCheck.java b/exist-core/src/main/java/org/exist/xquery/DynamicNameCheck.java
index b60a65ff469..ceb32d84450 100644
--- a/exist-core/src/main/java/org/exist/xquery/DynamicNameCheck.java
+++ b/exist-core/src/main/java/org/exist/xquery/DynamicNameCheck.java
@@ -21,11 +21,14 @@
*/
package org.exist.xquery;
+import org.exist.dom.INode;
import org.exist.dom.persistent.DocumentSet;
import org.exist.dom.persistent.NodeProxy;
import org.exist.dom.QName;
import org.exist.xquery.util.ExpressionDumper;
import org.exist.xquery.value.*;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
import org.w3c.dom.Node;
/**
@@ -77,56 +80,52 @@ public Sequence eval(Sequence contextSequence, Item contextItem) throws XPathExc
}
}
if (!Type.subTypeOf(itemType, test.getType())) {
- throw new XPathException(expression, "Type error in expression" +
+ throw new XPathException(expression, ErrorCodes.XPTY0004, "Type error in expression" +
": required type is " + Type.getTypeName(test.getType()) +
"; got: " + Type.getTypeName(item.getType()) + ": " + item.getStringValue());
}
final Node node = ((NodeValue) item).getNode();
- if (!test.matchesName(node))
- {throw new XPathException(expression, "Type error in expression: " +
- "required node name is " + getPrefixedNodeName(test.getName()) +
- "; got: " + getPrefixedNodeName(node));}
+ if (!test.matchesName(node)) {
+ throw new XPathException(expression, ErrorCodes.XPTY0004, "Type error in expression: " +
+ "required node name is " + getPrefixedNodeName(test) +
+ "; got: " + getPrefixedNodeName((INode) node));
}
- if (context.getProfiler().isEnabled()) {
- context.getProfiler().end(this, "", seq);
- }
- return seq;
- } catch(final IllegalArgumentException iae) {
- throw new XPathException(expression, iae);
}
+ if (context.getProfiler().isEnabled()) {
+ context.getProfiler().end(this, "", seq);
+ }
+ return seq;
+ } catch(final IllegalArgumentException iae) {
+ throw new XPathException(expression, iae);
+ }
}
- private String getPrefixedNodeName(Node node) {
- final String prefix = node.getPrefix();
- if (prefix == null) {
- final String nameSpace = node.getNamespaceURI();
- if (nameSpace == null) {
- return node.getNodeName();
- } else {
- return "{'" + nameSpace + "'}:" + node.getNodeName();
+ private String getPrefixedNodeName(final INode iNode) {
+ if (iNode instanceof Document) {
+ final Element documentElement = ((Document) iNode).getDocumentElement();
+ if (documentElement != null) {
+ return getPrefixedNodeName(true, ((INode) documentElement).getQName());
}
- } else if (prefix.isEmpty()) {
- return "{''}:" + node.getNodeName();
- } else {
- return prefix + ":" + node.getLocalName();
}
+ return getPrefixedNodeName(false, iNode.getQName());
}
- // TODO should be moved to QName
- private String getPrefixedNodeName(QName name) {
- final String prefix = name.getPrefix();
- final String localName = name.getLocalPart();
- if (prefix == null) {
- final String namespaceURI = name.getNamespaceURI();
- if (namespaceURI == null) {
- return localName;
- } else {
- return "{'" + namespaceURI + "'}:" + localName;
- }
- } else if (prefix.isEmpty()) {
- return "{''}:" + localName;
+ private String getPrefixedNodeName(final NameTest nameTest) {
+ return getPrefixedNodeName(nameTest.isOfType(Node.DOCUMENT_NODE), nameTest.getName());
+ }
+
+ private String getPrefixedNodeName(final boolean wasDocumentNodeWithNamedElementTest, final QName name) {
+ final String prefixedName;
+ if (name.getPrefix() == null && name.hasNamespace()) {
+ prefixedName = name.toURIQualifiedName();
+ } else {
+ prefixedName = name.getStringValue();
+ }
+
+ if (wasDocumentNodeWithNamedElementTest) {
+ return "document-node(" + prefixedName + ")";
} else {
- return prefix + ":" + localName;
+ return prefixedName;
}
}
diff --git a/exist-core/src/main/java/org/exist/xquery/NameTest.java b/exist-core/src/main/java/org/exist/xquery/NameTest.java
index 54c71eedb4f..3ad88f24dce 100644
--- a/exist-core/src/main/java/org/exist/xquery/NameTest.java
+++ b/exist-core/src/main/java/org/exist/xquery/NameTest.java
@@ -21,12 +21,15 @@
*/
package org.exist.xquery;
+import org.exist.dom.INode;
import org.exist.dom.persistent.NodeProxy;
import org.exist.dom.QName;
import org.exist.dom.memtree.NodeImpl;
import org.exist.dom.memtree.ReferenceNode;
import org.exist.xquery.util.ExpressionDumper;
import org.exist.xquery.value.Type;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.ProcessingInstruction;
@@ -96,6 +99,16 @@ public boolean matchesName(final Node other) {
return true;
}
+ if (nodeType == Type.DOCUMENT && other.getNodeType() == Node.DOCUMENT_NODE) {
+ final Element otherElement = ((Document) other).getDocumentElement();
+ if (otherElement != null) {
+ final QName otherQName = ((INode) otherElement).getQName();
+ if (nodeName.equals(otherQName)) {
+ return true;
+ }
+ }
+ }
+
if (!(nodeName instanceof QName.WildcardNamespaceURIQName)) {
String otherNs = other.getNamespaceURI();
if (otherNs == null) {
diff --git a/exist-core/src/test/xquery/node-tests.xqm b/exist-core/src/test/xquery/node-tests.xqm
new file mode 100644
index 00000000000..b36d0dd5d99
--- /dev/null
+++ b/exist-core/src/test/xquery/node-tests.xqm
@@ -0,0 +1,102 @@
+(:
+ : 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 nt = "http://exist-db.org/xquery/test/node-tests";
+
+import module namespace test="http://exist-db.org/xquery/xqsuite" at "resource:org/exist/xquery/lib/xqsuite/xqsuite.xql";
+
+
+declare %private function nt:f-document-node($a as document-node()) {
+ $a//text()
+};
+
+declare %private function nt:f-document-node-with-document-element($a as document-node(element())) {
+ $a//text()
+};
+
+declare %private function nt:f-document-node-with-named-document-element($a as document-node(element(a))) {
+ $a//text()
+};
+
+
+declare
+ %test:assertEmpty
+function nt:test-document-node-valid-1() {
+ nt:f-document-node(document { () })
+};
+
+declare
+ %test:assertEquals("is not b")
+function nt:test-document-node-valid-2() {
+ nt:f-document-node(document {is not b})
+};
+
+declare
+ %test:assertError("XPTY0004")
+function nt:test-document-node-invalid() {
+ nt:f-document-node(is not b)
+};
+
+declare
+ %test:assertEquals("is not b")
+function nt:test-document-node-with-document-element-valid() {
+ nt:f-document-node-with-document-element(document {is not b})
+};
+
+declare
+ %test:pending("BaseX returns an empty-sequence, but Saxon raises the error XPTY0004... which should it be?")
+ %test:assertError("XPTY0004")
+function nt:test-document-node-with-document-element-invalid-1() {
+ nt:f-document-node-with-document-element(document { () })
+};
+
+declare
+ %test:pending("BaseX returns an empty-sequence, but Saxon raises the error XPTY0004... which should it be?")
+ %test:assertError("XPTY0004")
+function nt:test-document-node-with-document-element-invalid-2() {
+ nt:f-document-node-with-document-element(document {})
+};
+
+declare
+ %test:assertEquals("is not b")
+function nt:test-document-node-with-named-document-element-valid() {
+ nt:f-document-node-with-named-document-element(document {is not b})
+};
+
+declare
+ %test:assertError("XPTY0004")
+function nt:test-document-node-with-named-document-element-invalid-1() {
+ nt:f-document-node-with-named-document-element(document { () })
+};
+
+declare
+ %test:assertError("XPTY0004")
+function nt:test-document-node-with-named-document-element-invalid-2() {
+ nt:f-document-node-with-named-document-element(document {})
+};
+
+declare
+ %test:assertError("XPTY0004")
+function nt:test-document-node-with-named-document-element-invalid-3() {
+ nt:f-document-node-with-named-document-element(document {is b})
+};