Skip to content

Commit efd22b2

Browse files
Merge branch 'main' into xmlns-parsing
2 parents 8665f67 + f01732f commit efd22b2

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

42 files changed

+534
-189
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,5 +4,6 @@
44
*.DS_Store
55
*.swp
66
*.out
7+
.claude/
78
.idea/
89
/target

basex-api/pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
</parent>
1313

1414
<properties>
15-
<jettyVersion>12.1.7</jettyVersion>
15+
<jettyVersion>12.1.8</jettyVersion>
1616
</properties>
1717

1818
<name>BaseX API</name>

basex-core/src/main/java/org/basex/io/serial/AdaptiveSerializer.java

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@
1313
import org.basex.query.value.item.*;
1414
import org.basex.query.value.map.*;
1515
import org.basex.query.value.node.*;
16-
import org.basex.query.value.seq.*;
1716
import org.basex.query.value.type.*;
1817
import org.basex.util.*;
1918

@@ -72,15 +71,15 @@ public final void serialize(final Item item) throws IOException {
7271

7372
@Override
7473
protected void jnode(final JNode jnode) throws IOException {
75-
if(jnode.key != Empty.VALUE) {
74+
if(jnode.isRoot()) {
75+
printChars(QueryText.JTREE);
76+
printChar('(');
77+
} else {
7678
printChars(Token.token(QueryText.JNODE));
7779
printChar('(');
7880
super.serialize(jnode.key);
7981
printChar(':');
8082
if(indent) printChar(' ');
81-
} else {
82-
printChars(QueryText.JTREE);
83-
printChar('(');
8483
}
8584
int cc = 0;
8685
if(jnode.value.size() > 1) printChar('(');

basex-core/src/main/java/org/basex/query/QueryParser.java

Lines changed: 18 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -539,14 +539,15 @@ private boolean defaultNamespaceDecl(final boolean fixed) throws QueryException
539539
final boolean elem = wsConsumeWs(ELEMENT);
540540
if(!elem && !wsConsumeWs(FUNCTION)) return false;
541541
wsCheck(NAMESPACE);
542-
final byte[] uri = uriLiteral();
542+
final byte[] uri = elem ? uriLiteral(ANY_URI) : uriLiteral();
543543
if(eq(XML_URI, uri)) throw error(BINDXMLURI_X_X, uri, XML);
544544
if(eq(XMLNS_URI, uri)) throw error(BINDXMLURI_X_X, uri, XMLNS);
545545

546546
if(elem) {
547547
if(!decl.add(ELEMENT)) throw error(DUPLNS);
548548
sc.elemNsFixed = fixed;
549-
sc.elemNS = uri.length == 0 ? null : uri;
549+
sc.elemNsAny = Token.eq(uri, QueryText.ANY_URI);
550+
sc.elemNS = sc.elemNsAny || uri.length == 0 ? null : uri;
550551
sc.dirNS = sc.elemNS;
551552
} else {
552553
if(!decl.add(FUNCTION)) throw error(DUPLNS);
@@ -697,7 +698,6 @@ private void schemaImport() throws QueryException {
697698
}
698699
final byte[] uri = uriLiteral();
699700
if(prefix != null && uri.length == 0) throw error(NSEMPTY);
700-
if(!Uri.get(uri).isValid()) throw error(INVURI_X, uri);
701701
addLocations(new TokenList());
702702
throw error(IMPLSCHEMA);
703703
}
@@ -715,7 +715,6 @@ private void moduleImport() throws QueryException {
715715

716716
final byte[] uri = uriLiteral();
717717
if(uri.length == 0) throw error(NSMODURI);
718-
if(!Uri.get(uri).isValid()) throw error(INVURI_X, uri);
719718
if(sc.imports.contains(token(uri))) throw error(DUPLMODULE_X, uri);
720719
sc.imports.add(uri);
721720

@@ -754,8 +753,7 @@ private boolean addLocations(final TokenList list) throws QueryException {
754753
if(add) {
755754
do {
756755
final byte[] uri = uriLiteral();
757-
if(!Uri.get(uri).isValid() || IO.get(string(uri)) instanceof IOContent)
758-
throw error(INVURI_X, uri);
756+
if(IO.get(string(uri)) instanceof IOContent) throw error(INVURI_X, uri);
759757
list.add(uri);
760758
} while(wsConsume(","));
761759
}
@@ -955,7 +953,7 @@ private static boolean reserved(final QNm name) {
955953
* @throws QueryException query exception
956954
*/
957955
private void typeDecl(final AnnList anns) throws QueryException {
958-
final QNm qn = eQName(sc.elemNS, TYPENAME);
956+
final QNm qn = eQName(sc.elemNsAny ? XS_URI : sc.elemNS, TYPENAME);
959957
if(declaredTypes.contains(qn)) throw error(DUPLTYPE_X, qn.string());
960958
if(NSGlobal.reserved(qn.uri())) throw error(TYPERESERVED_X, qn.string());
961959
wsCheck(AS);
@@ -2459,12 +2457,14 @@ private ExprInfo simpleNodeTest(final Kind kind, final boolean all) throws Query
24592457
} else {
24602458
NameTest.Scope scope = NameTest.Scope.FULL;
24612459
if(!name.hasPrefix()) {
2460+
pos = p;
24622461
if(consume(":*")) {
24632462
// name test: prefix:*
24642463
name = new QNm(concat(name.string(), cpToken(':')));
24652464
scope = NameTest.Scope.URI;
24662465
} else if(!eqName) {
2467-
scope = NameTest.Scope.FLEXIBLE;
2466+
scope = kind == Kind.ELEMENT && sc.elemNsAny ? NameTest.Scope.LOCAL
2467+
: NameTest.Scope.FLEXIBLE;
24682468
}
24692469
}
24702470
// name test: prefix:name, name, Q{uri}name
@@ -2875,11 +2875,15 @@ private byte[] stringLiteral() throws QueryException {
28752875

28762876
/**
28772877
* Parses the "URILiteral" rule.
2878+
* @param special tokens that are allowed though not valid URI literals
28782879
* @return query expression
28792880
* @throws QueryException query exception
28802881
*/
2881-
private byte[] uriLiteral() throws QueryException {
2882-
return normalize(stringLiteral());
2882+
private byte[] uriLiteral(final byte[]... special) throws QueryException {
2883+
final byte[] uri = normalize(stringLiteral());
2884+
for(final byte[] sp : special) if(eq(uri, sp)) return uri;
2885+
if(!Uri.get(uri).isValid()) throw error(INVURI_X, uri);
2886+
return uri;
28832887
}
28842888

28852889
/**
@@ -2895,6 +2899,7 @@ private byte[] bracedURILiteral() throws QueryException {
28952899
entity(token);
28962900
}
28972901
final byte[] ns = normalize(token.toArray());
2902+
if(!Uri.get(ns).isValid()) throw error(INVURI_X, ns);
28982903
if(eq(ns, XMLNS_URI)) {
28992904
pos = p;
29002905
throw error(ILLEGALEQNAME_X, ns);
@@ -3493,7 +3498,7 @@ private SeqType castTarget() throws QueryException {
34933498
if(wsConsume("(")) {
34943499
type = choiceItemType().type;
34953500
} else {
3496-
final QNm name = eQName(sc.elemNS, TYPEINVALID);
3501+
final QNm name = eQName(sc.elemNsAny ? XS_URI : sc.elemNS, TYPEINVALID);
34973502
if(!name.hasURI() && eq(name.local(), token(ENUM))) {
34983503
if(!wsConsume("(")) throw error(WHICHCAST_X, BasicType.similar(name));
34993504
type = enumerationType();
@@ -3582,8 +3587,8 @@ private SeqType itemType() throws QueryException {
35823587
}
35833588
}
35843589
} else {
3585-
// attach default element namespace
3586-
if(!name.hasURI()) name.uri(sc.elemNS);
3590+
// attach default element namespace, or schema namespace if default element namespace is ##any
3591+
if(!name.hasURI()) name.uri(sc.elemNsAny ? XS_URI : sc.elemNS);
35873592
// basic type
35883593
type = BasicType.get(name, false);
35893594
// declared type

basex-core/src/main/java/org/basex/query/QueryText.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -340,6 +340,8 @@ public interface QueryText {
340340
/** BaseX URI. */ byte[] XQUERY_URI = token(BXMODULES_URL + "xquery");
341341
/** BaseX URI. */ byte[] XSLT_URI = token(BXMODULES_URL + "xslt");
342342

343+
/** "Any" URI. */ byte[] ANY_URI = token("##any");
344+
343345
// QUERY PLAN ===================================================================================
344346

345347
/** Query Info. */ String OP = "op";

basex-core/src/main/java/org/basex/query/StaticContext.java

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,8 @@ public final class StaticContext {
3838
public Collation collation;
3939
/** Default element/type namespace fixed flag. */
4040
public boolean elemNsFixed;
41+
/** Default element/type namespace ##any flag. */
42+
public boolean elemNsAny;
4143
/** Default element/type namespace. */
4244
public byte[] elemNS;
4345
/** Direct element constructor default element/type namespace (differs from above if "fixed"). */
@@ -92,13 +94,16 @@ public StaticContext(final QueryContext qc) {
9294
* @throws QueryException query exception
9395
*/
9496
void namespace(final String prefix, final String uri) throws QueryException {
95-
if(prefix.isEmpty()) {
96-
elemNS = uri.isEmpty() ? null : token(uri);
97+
final byte[] prefix1 = token(prefix);
98+
final byte[] u = token(uri);
99+
if(prefix1.length == 0) {
100+
elemNsAny = Token.eq(u, QueryText.ANY_URI);
101+
elemNS = elemNsAny || u.length == 0 ? null : u;
97102
dirNS = elemNS;
98-
} else if(uri.isEmpty()) {
99-
ns.delete(token(prefix));
103+
} else if(u.length == 0) {
104+
ns.delete(prefix1);
100105
} else {
101-
ns.add(token(prefix), token(uri), null);
106+
ns.add(prefix1, u, null);
102107
}
103108
}
104109

basex-core/src/main/java/org/basex/query/expr/constr/CMap.java

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
import org.basex.query.value.*;
1414
import org.basex.query.value.item.*;
1515
import org.basex.query.value.map.*;
16+
import org.basex.query.value.node.*;
1617
import org.basex.query.value.seq.*;
1718
import org.basex.query.value.type.*;
1819
import org.basex.query.var.*;
@@ -157,9 +158,19 @@ public XQMap item(final QueryContext qc, final InputInfo ii) throws QueryExcepti
157158
if(exprs[e + 1] != Empty.UNDEFINED) {
158159
add.accept(toAtomItem(exprs[e], qc), exprs[e + 1].value(qc));
159160
} else {
160-
final Iter iter = exprs[e].unwrappedIter(qc);
161+
final Iter iter = exprs[e].iter(qc);
161162
for(Item item; (item = iter.next()) != null;) {
162-
toMap(item).forEach(add);
163+
Item it;
164+
if(item instanceof final JNode jnode) {
165+
if(jnode.isRoot()) {
166+
it = (Item) jnode.value;
167+
} else {
168+
it = XQMap.get(jnode.key, jnode.value);
169+
}
170+
} else {
171+
it = item;
172+
}
173+
toMap(it).forEach(add);
163174
}
164175
}
165176
}

basex-core/src/main/java/org/basex/query/expr/gflwor/GFLWOR.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1038,12 +1038,12 @@ public Expr copy(final CompileContext cc, final IntObjectMap<Var> vm) {
10381038
}
10391039

10401040
/**
1041-
* Checks if this FLWOR expression has only 'for', 'let', 'where', and 'while' clauses.
1041+
* Checks if this FLWOR expression has only 'for', 'let', and 'where' clauses.
10421042
* @return result of check
10431043
*/
10441044
private boolean isFLW() {
10451045
return ((Checks<Clause>) clause -> clause instanceof For || clause instanceof Let ||
1046-
clause instanceof Where || clause instanceof While).all(clauses);
1046+
clause instanceof Where).all(clauses);
10471047
}
10481048

10491049
@Override

basex-core/src/main/java/org/basex/query/expr/path/JNodeTest.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -82,8 +82,7 @@ public static boolean equals(final Value v1, final Value v2) {
8282
@Override
8383
public boolean matches(final GNode node) {
8484
if(node instanceof final JNode jnode) {
85-
final Item k1 = key, k2 = jnode.key;
86-
return (k1 == null || (k1 == Empty.VALUE ? k2 == Empty.VALUE : equals(k1, k2))) &&
85+
return (key == null || (key == Empty.VALUE ? jnode.isRoot() : equals(key, jnode.key))) &&
8786
valueType.instance(jnode.value);
8887
}
8988
return false;

basex-core/src/main/java/org/basex/query/expr/path/NameTest.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44
import org.basex.query.*;
55
import org.basex.query.value.item.*;
66
import org.basex.query.value.node.*;
7-
import org.basex.query.value.seq.*;
87
import org.basex.query.value.type.*;
98
import org.basex.util.*;
109

@@ -123,7 +122,7 @@ public boolean matches(final GNode node) {
123122
if(node instanceof final JNode jnode) {
124123
// JNodes
125124
if(scope == Scope.ALL) return true;
126-
if(jnode.key == Empty.VALUE) return false;
125+
if(jnode.isRoot()) return false;
127126
if(scope == Scope.FLEXIBLE) {
128127
try {
129128
return Token.eq(qname.string(), jnode.key.string(null));

0 commit comments

Comments
 (0)