Example #1
0
  /**
   * Performs the attribute function.
   *
   * @param ctx query context
   * @return iterator
   * @throws QueryException query exception
   */
  private Iter attribute(final QueryContext ctx) throws QueryException {
    final IndexContext ic = new IndexContext(ctx, data(0, ctx), null, true);
    final IndexAccess ia = new IndexAccess(input, expr[1], IndexType.ATTRIBUTE, ic);

    // return iterator if no name test is specified
    if (expr.length < 3) return ia.iter(ctx);

    // parse and compile the name test
    final Item name = checkNoEmpty(expr[2].item(ctx, input));
    final QNm nm = new QNm(checkStr(name, ctx), ctx);
    if (!nm.hasPrefix()) nm.uri(ctx.sc.ns.uri(EMPTY));

    final NameTest nt = new NameTest(nm, NameTest.Name.STD, true);
    // no results expected: return empty sequence
    if (!nt.comp(ctx)) return Empty.ITER;

    // wrap iterator with name test
    return new Iter() {
      final NodeIter ir = ia.iter(ctx);

      @Override
      public ANode next() throws QueryException {
        ANode n;
        while ((n = ir.next()) != null && !nt.eval(n)) ;
        return n;
      }
    };
  }
Example #2
0
  @Override
  public FElem item(final QueryContext ctx, final InputInfo ii) throws QueryException {

    final int s = prepare(ctx);
    try {
      // adds in-scope namespaces
      final Atts ns = new Atts();
      for (int i = 0; i < nspaces.size(); ++i) {
        ns.add(nspaces.name(i), nspaces.string(i));
      }

      // create and check QName
      final QNm nm = qname(ctx, ii);
      final byte[] cp = nm.prefix(), cu = nm.uri();
      if (eq(cp, XML) ^ eq(cu, XMLURI)) CEXML.thrw(input, cu, cp);
      if (eq(cu, XMLNSURI)) CEINV.thrw(input, cu);
      if (eq(cp, XMLNS)) CEINV.thrw(input, cp);

      // analyze element namespace unless it is "xml"
      if (!eq(cp, XML)) {
        // request namespace for the specified uri
        final byte[] uri = ctx.sc.ns.uri(cp);

        // check if element has a namespace
        if (nm.hasURI()) {
          // add to statically known namespaces
          if (!comp && (uri == null || !eq(uri, cu))) ctx.sc.ns.add(cp, cu);
          // add to in-scope namespaces
          if (!ns.contains(cp)) ns.add(cp, cu);
        } else {
          // element has no namespace: assign default uri
          nm.uri(uri);
        }
      }

      // create child and attribute nodes
      final Constr constr = new Constr(ii, ctx).add(expr);
      if (constr.errAtt) NOATTALL.thrw(input);
      if (constr.errNS) NONSALL.thrw(input);
      if (constr.duplAtt != null) (comp ? CATTDUPL : ATTDUPL).thrw(input, constr.duplAtt);
      if (constr.duplNS != null) DUPLNSCONS.thrw(input, constr.duplNS);

      // create node
      final FElem node = new FElem(nm, constr.children, constr.atts, ns);

      // add namespaces from constructor
      final Atts cns = constr.nspaces;
      for (int a = 0; a < cns.size(); ++a) {
        addNS(cns.name(a), cns.string(a), ns);
      }

      // update parent references of attributes and add namespaces
      for (int a = 0; a < constr.atts.size(); ++a) {
        constr.atts.get(a).parent(node);

        final ANode att = constr.atts.get(a);
        final QNm qnm = att.qname();
        // skip attributes without prefixes or URIs
        if (!qnm.hasPrefix() || !qnm.hasURI()) continue;

        // skip XML namespace
        final byte[] apref = qnm.prefix();
        if (eq(apref, XML)) continue;

        final byte[] auri = qnm.uri();
        final byte[] npref = addNS(apref, auri, ns);
        if (npref != null) {
          constr.atts.item[a] =
              new FAttr(new QNm(concat(npref, COLON, qnm.local()), auri), att.string());
        }
      }

      // add inherited namespaces
      final Atts stack = ctx.sc.ns.stack();
      for (int a = stack.size() - 1; a >= 0; a--) {
        final byte[] pref = stack.name(a);
        if (!ns.contains(pref)) ns.add(pref, stack.string(a));
      }

      // update parent references of children
      for (int c = 0; c < constr.children.size(); ++c) {
        final ANode child = constr.children.get(c).parent(node);
        // add inherited and remove unused namespaces
        if (child.type == NodeType.ELM) {
          if (ctx.sc.nsInherit) inherit(child, ns);
          if (!ctx.sc.nsPreserve) noPreserve(child);
          child.optimize();
        }
      }

      // return generated and optimized node
      return node.optimize();

    } finally {
      ctx.sc.ns.size(s);
    }
  }