Skip to content

Commit 6f8e3bf

Browse files
authored
Merge pull request #4395 from evolvedbinary/hotfix/document-node-test
Fix the Node Test for document-node(element(name))
2 parents 8e0c4ae + 3f4028a commit 6f8e3bf

File tree

3 files changed

+151
-37
lines changed

3 files changed

+151
-37
lines changed

exist-core/src/main/java/org/exist/xquery/DynamicNameCheck.java

Lines changed: 36 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -21,11 +21,14 @@
2121
*/
2222
package org.exist.xquery;
2323

24+
import org.exist.dom.INode;
2425
import org.exist.dom.persistent.DocumentSet;
2526
import org.exist.dom.persistent.NodeProxy;
2627
import org.exist.dom.QName;
2728
import org.exist.xquery.util.ExpressionDumper;
2829
import org.exist.xquery.value.*;
30+
import org.w3c.dom.Document;
31+
import org.w3c.dom.Element;
2932
import org.w3c.dom.Node;
3033

3134
/**
@@ -77,56 +80,52 @@ public Sequence eval(Sequence contextSequence, Item contextItem) throws XPathExc
7780
}
7881
}
7982
if (!Type.subTypeOf(itemType, test.getType())) {
80-
throw new XPathException(expression, "Type error in expression" +
83+
throw new XPathException(expression, ErrorCodes.XPTY0004, "Type error in expression" +
8184
": required type is " + Type.getTypeName(test.getType()) +
8285
"; got: " + Type.getTypeName(item.getType()) + ": " + item.getStringValue());
8386
}
8487
final Node node = ((NodeValue) item).getNode();
85-
if (!test.matchesName(node))
86-
{throw new XPathException(expression, "Type error in expression: " +
87-
"required node name is " + getPrefixedNodeName(test.getName()) +
88-
"; got: " + getPrefixedNodeName(node));}
88+
if (!test.matchesName(node)) {
89+
throw new XPathException(expression, ErrorCodes.XPTY0004, "Type error in expression: " +
90+
"required node name is " + getPrefixedNodeName(test) +
91+
"; got: " + getPrefixedNodeName((INode) node));
8992
}
90-
if (context.getProfiler().isEnabled()) {
91-
context.getProfiler().end(this, "", seq);
92-
}
93-
return seq;
94-
} catch(final IllegalArgumentException iae) {
95-
throw new XPathException(expression, iae);
9693
}
94+
if (context.getProfiler().isEnabled()) {
95+
context.getProfiler().end(this, "", seq);
96+
}
97+
return seq;
98+
} catch(final IllegalArgumentException iae) {
99+
throw new XPathException(expression, iae);
100+
}
97101
}
98102

99-
private String getPrefixedNodeName(Node node) {
100-
final String prefix = node.getPrefix();
101-
if (prefix == null) {
102-
final String nameSpace = node.getNamespaceURI();
103-
if (nameSpace == null) {
104-
return node.getNodeName();
105-
} else {
106-
return "{'" + nameSpace + "'}:" + node.getNodeName();
103+
private String getPrefixedNodeName(final INode iNode) {
104+
if (iNode instanceof Document) {
105+
final Element documentElement = ((Document) iNode).getDocumentElement();
106+
if (documentElement != null) {
107+
return getPrefixedNodeName(true, ((INode) documentElement).getQName());
107108
}
108-
} else if (prefix.isEmpty()) {
109-
return "{''}:" + node.getNodeName();
110-
} else {
111-
return prefix + ":" + node.getLocalName();
112109
}
110+
return getPrefixedNodeName(false, iNode.getQName());
113111
}
114112

115-
// TODO should be moved to QName
116-
private String getPrefixedNodeName(QName name) {
117-
final String prefix = name.getPrefix();
118-
final String localName = name.getLocalPart();
119-
if (prefix == null) {
120-
final String namespaceURI = name.getNamespaceURI();
121-
if (namespaceURI == null) {
122-
return localName;
123-
} else {
124-
return "{'" + namespaceURI + "'}:" + localName;
125-
}
126-
} else if (prefix.isEmpty()) {
127-
return "{''}:" + localName;
113+
private String getPrefixedNodeName(final NameTest nameTest) {
114+
return getPrefixedNodeName(nameTest.isOfType(Node.DOCUMENT_NODE), nameTest.getName());
115+
}
116+
117+
private String getPrefixedNodeName(final boolean wasDocumentNodeWithNamedElementTest, final QName name) {
118+
final String prefixedName;
119+
if (name.getPrefix() == null && name.hasNamespace()) {
120+
prefixedName = name.toURIQualifiedName();
121+
} else {
122+
prefixedName = name.getStringValue();
123+
}
124+
125+
if (wasDocumentNodeWithNamedElementTest) {
126+
return "document-node(" + prefixedName + ")";
128127
} else {
129-
return prefix + ":" + localName;
128+
return prefixedName;
130129
}
131130
}
132131

exist-core/src/main/java/org/exist/xquery/NameTest.java

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,12 +21,15 @@
2121
*/
2222
package org.exist.xquery;
2323

24+
import org.exist.dom.INode;
2425
import org.exist.dom.persistent.NodeProxy;
2526
import org.exist.dom.QName;
2627
import org.exist.dom.memtree.NodeImpl;
2728
import org.exist.dom.memtree.ReferenceNode;
2829
import org.exist.xquery.util.ExpressionDumper;
2930
import org.exist.xquery.value.Type;
31+
import org.w3c.dom.Document;
32+
import org.w3c.dom.Element;
3033
import org.w3c.dom.Node;
3134
import org.w3c.dom.ProcessingInstruction;
3235

@@ -96,6 +99,16 @@ public boolean matchesName(final Node other) {
9699
return true;
97100
}
98101

102+
if (nodeType == Type.DOCUMENT && other.getNodeType() == Node.DOCUMENT_NODE) {
103+
final Element otherElement = ((Document) other).getDocumentElement();
104+
if (otherElement != null) {
105+
final QName otherQName = ((INode) otherElement).getQName();
106+
if (nodeName.equals(otherQName)) {
107+
return true;
108+
}
109+
}
110+
}
111+
99112
if (!(nodeName instanceof QName.WildcardNamespaceURIQName)) {
100113
String otherNs = other.getNamespaceURI();
101114
if (otherNs == null) {
Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
(:
2+
: eXist-db Open Source Native XML Database
3+
: Copyright (C) 2001 The eXist-db Authors
4+
:
5+
6+
: http://www.exist-db.org
7+
:
8+
: This library is free software; you can redistribute it and/or
9+
: modify it under the terms of the GNU Lesser General Public
10+
: License as published by the Free Software Foundation; either
11+
: version 2.1 of the License, or (at your option) any later version.
12+
:
13+
: This library is distributed in the hope that it will be useful,
14+
: but WITHOUT ANY WARRANTY; without even the implied warranty of
15+
: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16+
: Lesser General Public License for more details.
17+
:
18+
: You should have received a copy of the GNU Lesser General Public
19+
: License along with this library; if not, write to the Free Software
20+
: Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21+
:)
22+
xquery version "3.1";
23+
24+
module namespace nt = "http://exist-db.org/xquery/test/node-tests";
25+
26+
import module namespace test="http://exist-db.org/xquery/xqsuite" at "resource:org/exist/xquery/lib/xqsuite/xqsuite.xql";
27+
28+
29+
declare %private function nt:f-document-node($a as document-node()) {
30+
$a//text()
31+
};
32+
33+
declare %private function nt:f-document-node-with-document-element($a as document-node(element())) {
34+
$a//text()
35+
};
36+
37+
declare %private function nt:f-document-node-with-named-document-element($a as document-node(element(a))) {
38+
$a//text()
39+
};
40+
41+
42+
declare
43+
%test:assertEmpty
44+
function nt:test-document-node-valid-1() {
45+
nt:f-document-node(document { () })
46+
};
47+
48+
declare
49+
%test:assertEquals("is not b")
50+
function nt:test-document-node-valid-2() {
51+
nt:f-document-node(document {<a>is not b</a>})
52+
};
53+
54+
declare
55+
%test:assertError("XPTY0004")
56+
function nt:test-document-node-invalid() {
57+
nt:f-document-node(<a>is not b</a>)
58+
};
59+
60+
declare
61+
%test:assertEquals("is not b")
62+
function nt:test-document-node-with-document-element-valid() {
63+
nt:f-document-node-with-document-element(document {<a>is not b</a>})
64+
};
65+
66+
declare
67+
%test:pending("BaseX returns an empty-sequence, but Saxon raises the error XPTY0004... which should it be?")
68+
%test:assertError("XPTY0004")
69+
function nt:test-document-node-with-document-element-invalid-1() {
70+
nt:f-document-node-with-document-element(document { () })
71+
};
72+
73+
declare
74+
%test:pending("BaseX returns an empty-sequence, but Saxon raises the error XPTY0004... which should it be?")
75+
%test:assertError("XPTY0004")
76+
function nt:test-document-node-with-document-element-invalid-2() {
77+
nt:f-document-node-with-document-element(document {<!-- comment -->})
78+
};
79+
80+
declare
81+
%test:assertEquals("is not b")
82+
function nt:test-document-node-with-named-document-element-valid() {
83+
nt:f-document-node-with-named-document-element(document {<a>is not b</a>})
84+
};
85+
86+
declare
87+
%test:assertError("XPTY0004")
88+
function nt:test-document-node-with-named-document-element-invalid-1() {
89+
nt:f-document-node-with-named-document-element(document { () })
90+
};
91+
92+
declare
93+
%test:assertError("XPTY0004")
94+
function nt:test-document-node-with-named-document-element-invalid-2() {
95+
nt:f-document-node-with-named-document-element(document {<!-- comment -->})
96+
};
97+
98+
declare
99+
%test:assertError("XPTY0004")
100+
function nt:test-document-node-with-named-document-element-invalid-3() {
101+
nt:f-document-node-with-named-document-element(document {<b>is b</b>})
102+
};

0 commit comments

Comments
 (0)