/** * Returns all namespace keys and values. Should be only called for element nodes. * * @param pre pre value * @return key and value ids */ public final Atts ns(final int pre) { final Atts as = new Atts(); if (nsFlag(pre)) { final int[] nsp = nspaces.get(pre, this); for (int n = 0; n < nsp.length; n += 2) as.add(nspaces.prefix(nsp[n]), nspaces.uri(nsp[n + 1])); } return as; }
@Override protected void finishOpen() throws IOException { try { final AttributesImpl attrs = new AttributesImpl(); final int as = attributes.size(); for (int a = 0; a < as; a++) { final byte[] name = attributes.name(a); final String uri = string(namespaces.get(prefix(name))); final String lname = string(local(name)); final String rname = string(name); final String value = string(attributes.value(a)); attrs.addAttribute(uri, lname, rname, null, value); } final String uri = string(namespaces.get(elem.prefix())); final String lname = string(elem.local()); final String rname = string(elem.string()); contentHandler.startElement(uri, lname, rname, attrs); } catch (final SAXException ex) { throw new IOException(ex); } }
@Override protected void attribute(final byte[] name, final byte[] value, final boolean standalone) { byte[] prefix = null; if (startsWith(name, XMLNS)) { if (name.length == 5) { prefix = EMPTY; } else if (name[5] == ':') { prefix = substring(name, 6); } } if (prefix != null) { namespaces.put(prefix, value); } else { attributes.add(name, value); } }
/** * Inserts a data instance at the specified pre value. Note that the specified data instance must * differ from this instance. * * @param ipre value at which to insert new data * @param ipar parent pre value of node * @param clip data clip */ public final void insert(final int ipre, final int ipar, final DataClip clip) { meta.update(); // update value and document indexes if (meta.updindex) indexBegin(); resources.insert(ipre, clip); final int dsize = clip.size(); final int buf = Math.min(dsize, IO.BLOCKSIZE >> IO.NODEPOWER); // resize buffer to cache more entries buffer(buf); // find all namespaces in scope to avoid duplicate declarations final TokenMap nsScope = nspaces.scope(ipar, this); // loop through all entries final IntList preStack = new IntList(); final NSNode nsRoot = nspaces.current(); final HashSet<NSNode> newNodes = new HashSet<NSNode>(); final IntList flagPres = new IntList(); // indicates if database only contains a dummy node final Data data = clip.data; int c = 0; for (int dpre = clip.start; dpre < clip.end; ++dpre, ++c) { if (c != 0 && c % buf == 0) insert(ipre + c - buf); final int pre = ipre + c; final int dkind = data.kind(dpre); final int dpar = data.parent(dpre, dkind); // ipar < 0 if document nodes on top level are added final int dis = dpar >= 0 ? dpre - dpar : ipar >= 0 ? pre - ipar : 0; final int par = dis == 0 ? -1 : pre - dis; if (c == 0) nspaces.root(par, this); while (!preStack.isEmpty() && preStack.peek() > par) nspaces.close(preStack.pop()); switch (dkind) { case DOC: // add document nspaces.prepare(); final int s = data.size(dpre, dkind); doc(pre, s, data.text(dpre, true)); meta.ndocs++; preStack.push(pre); break; case ELEM: // add element nspaces.prepare(); boolean ne = false; if (data.nsFlag(dpre)) { final Atts at = data.ns(dpre); for (int a = 0; a < at.size(); ++a) { // see if prefix has been declared/ is part of current ns scope final byte[] old = nsScope.get(at.name(a)); if (old == null || !eq(old, at.value(a))) { // we have to keep track of all new NSNodes that are added // to the Namespace structure, as their pre values must not // be updated. I.e. if an NSNode N with pre value 3 existed // prior to inserting and two new nodes are inserted at // location pre == 3 we have to make sure N and only N gets // updated. newNodes.add(nspaces.add(at.name(a), at.value(a), pre)); ne = true; } } } byte[] nm = data.name(dpre, dkind); elem( dis, tagindex.index(nm, null, false), data.attSize(dpre, dkind), data.size(dpre, dkind), nspaces.uri(nm, true), ne); preStack.push(pre); break; case TEXT: case COMM: case PI: // add text text(pre, dis, data.text(dpre, true), dkind); break; case ATTR: // add attribute nm = data.name(dpre, dkind); // check if prefix already in nsScope or not final byte[] attPref = prefix(nm); // check if prefix of attribute has already been declared, otherwise // add declaration to parent node if (data.nsFlag(dpre) && nsScope.get(attPref) == null) { nspaces.add( par, preStack.isEmpty() ? -1 : preStack.peek(), attPref, data.nspaces.uri(data.uri(dpre, dkind)), this); // save pre value to set ns flag later for this node. can't be done // here as direct table access would interfere with the buffer flagPres.add(par); } attr( pre, dis, atnindex.index(nm, null, false), data.text(dpre, false), nspaces.uri(nm, false), false); break; } } // finalize and update namespace structure while (!preStack.isEmpty()) nspaces.close(preStack.pop()); nspaces.root(nsRoot); if (bp != 0) insert(ipre + c - 1 - (c - 1) % buf); // reset buffer to old size buffer(1); // set ns flags for (int f = 0; f < flagPres.size(); f++) { final int fl = flagPres.get(f); table.write2(fl, 1, name(fl) | 1 << 15); } // increase size of ancestors int p = ipar; while (p >= 0) { final int k = kind(p); size(p, k, size(p, k) + dsize); p = parent(p, k); } if (meta.updindex) { // add the entries to the ID -> PRE mapping: idmap.insert(ipre, id(ipre), dsize); indexEnd(); } if (!cache) updateDist(ipre + dsize, dsize); // propagate PRE value shifts to namespaces if (ipar != -1) nspaces.insert(ipre, dsize, newNodes); }
/** * Stores a new prefix and namespace. * * @param prefix prefix * @param uri namespace uri */ private void put(final byte[] prefix, final byte[] uri) { if (decls == null) decls = new Atts(); decls.add(prefix, uri); }
@Override protected void startOpen(final QNm name) { namespaces = new NSDecl(namespaces); attributes.clear(); }
/** * Finds the prefix for the specified uri. * * @param uri namespace uri * @return prefix, or empty string */ public static byte[] prefix(final byte[] uri) { for (int s = NS.size() - 1; s >= 0; s--) { if (eq(NS.string(s), uri)) return NS.name(s); } return EMPTY; }
/** * Finds the specified namespace uri. * * @param pref prefix of the namespace * @return uri, or {@code null} */ public static byte[] uri(final byte[] pref) { for (int s = NS.size() - 1; s >= 0; s--) { if (eq(NS.name(s), pref)) return NS.string(s); } return null; }
static { // reserved namespaces NS.add(XML, XMLURI); NS.add(XS, XSURI); NS.add(XSI, XSIURI); NS.add(FN, FNURI); NS.add(MATH, MATHURI); NS.add(MAP, MAPURI); NS.add(ANN, ANNURI); RESERVED = NS.size(); // implementation-defined pre-declarations NS.add(LOCAL, LOCALURI); NS.add(OUTPUT, OUTPUTURI); NS.add(ERR, ERRORURI); // EXPath namespaces NS.add(EXPERR, EXPERROR); NS.add(CRYPTO, CRYPTOURI); NS.add(FILE, FILEURI); NS.add(HTTP, HTTPURI); NS.add(PKG, PKGURI); NS.add(ZIP, ZIPURI); // EXQuery namespaces NS.add(RESTXQ, RESTXQURI); // BaseX namespaces NS.add(BXERR, BXERRORS); NS.add(BASEX, BASEXURI); NS.add(ADMIN, ADMINURI); NS.add(ARCHIVE, ARCHIVEURI); NS.add(CLIENT, CLIENTURI); NS.add(CONVERT, CONVERTURI); NS.add(DB, DBURI); NS.add(FETCH, FETCHURI); NS.add(FT, FTURI); NS.add(HASH, HASHURI); NS.add(HOF, HOFURI); NS.add(HTML, HTMLURI); NS.add(INDEX, INDEXURI); NS.add(JSON, JSONURI); NS.add(OUT, OUTURI); NS.add(PROC, PROCURI); NS.add(PROF, PROFURI); NS.add(QUERY, QUERYURI); NS.add(RANDOM, RANDOMURI); NS.add(REPO, REPOURI); NS.add(SQL, SQLURI); NS.add(STREAM, STREAMURI); NS.add(VLDT, VALIDATEURI); NS.add(XSLT, XSLTURI); NS.add(XQRY, XQUERYURI); NS.add(XQUNIT, XQUNITURI); }
/** * Checks if the specified uri is a reserved namespace. * * @param uri uri to be checked * @return result of check */ public static boolean reserved(final byte[] uri) { for (int s = RESERVED - 1; s >= 0; s--) { if (eq(NS.string(s), uri)) return true; } return false; }