Skip to content

Commit

Permalink
[bugfix] Fix the Node Test for document-node(element(name))
Browse files Browse the repository at this point in the history
  • Loading branch information
adamretter committed May 21, 2022
1 parent 527094d commit 3f4028a
Show file tree
Hide file tree
Showing 3 changed files with 151 additions and 37 deletions.
73 changes: 36 additions & 37 deletions exist-core/src/main/java/org/exist/xquery/DynamicNameCheck.java
Original file line number Diff line number Diff line change
Expand Up @@ -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;

/**
Expand Down Expand Up @@ -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;
}
}

Expand Down
13 changes: 13 additions & 0 deletions exist-core/src/main/java/org/exist/xquery/NameTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down Expand Up @@ -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) {
Expand Down
102 changes: 102 additions & 0 deletions exist-core/src/test/xquery/node-tests.xqm
Original file line number Diff line number Diff line change
@@ -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 {<a>is not b</a>})
};

declare
%test:assertError("XPTY0004")
function nt:test-document-node-invalid() {
nt:f-document-node(<a>is not b</a>)
};

declare
%test:assertEquals("is not b")
function nt:test-document-node-with-document-element-valid() {
nt:f-document-node-with-document-element(document {<a>is not b</a>})
};

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 {<!-- comment -->})
};

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 {<a>is not b</a>})
};

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 {<!-- comment -->})
};

declare
%test:assertError("XPTY0004")
function nt:test-document-node-with-named-document-element-invalid-3() {
nt:f-document-node-with-named-document-element(document {<b>is b</b>})
};

0 comments on commit 3f4028a

Please sign in to comment.