private void processElement(String defaultNamespace, Properties namespaces) throws Exception {
    String fullName = XMLUtil.scanIdentifier(reader);
    String name = fullName;
    XMLUtil.skipWhitespace(reader, null);
    String prefix = null;
    int colonIndex = name.indexOf(':');

    if (colonIndex > 0) {
      prefix = name.substring(0, colonIndex);
      name = name.substring(colonIndex + 1);
    }

    List<String> attrNames = new ArrayList<>();
    List<String> attrValues = new ArrayList<>();
    List<String> attrTypes = new ArrayList<>();

    validator.elementStarted(fullName, reader.getSystemID(), reader.getLineNr());
    char ch;

    for (; ; ) {
      ch = reader.read();

      if ((ch == '/') || (ch == '>')) {
        break;
      }

      reader.unread(ch);
      processAttribute(attrNames, attrValues, attrTypes);
      XMLUtil.skipWhitespace(reader, null);
    }

    Properties extraAttributes = new Properties();
    validator.elementAttributesProcessed(fullName, extraAttributes, reader.getSystemID(), reader.getLineNr());
    Enumeration<Object> enumeration = extraAttributes.keys();

    while (enumeration.hasMoreElements()) {
      String key = (String)enumeration.nextElement();
      String value = extraAttributes.getProperty(key);
      attrNames.add(key);
      attrValues.add(value);
      attrTypes.add("CDATA");
    }

    for (int i = 0; i < attrNames.size(); i++) {
      String key = attrNames.get(i);
      String value = attrValues.get(i);

      if (key.equals("xmlns")) {
        defaultNamespace = value;
      }
      else if (key.startsWith("xmlns:")) {
        namespaces.setProperty(key.substring(6), value);
      }
    }

    if (prefix == null) {
      builder.startElement(name, prefix, defaultNamespace, reader.getSystemID(), reader.getLineNr());
    }
    else {
      builder.startElement(name, prefix, namespaces.getProperty(prefix), reader.getSystemID(), reader.getLineNr());
    }

    for (int i = 0; i < attrNames.size(); i++) {
      String key = attrNames.get(i);

      if (key.startsWith("xmlns")) {
        continue;
      }

      String value = attrValues.get(i);
      String type = attrTypes.get(i);
      colonIndex = key.indexOf(':');

      if (colonIndex > 0) {
        String attPrefix = key.substring(0, colonIndex);
        key = key.substring(colonIndex + 1);
        builder.addAttribute(key, attPrefix, namespaces.getProperty(attPrefix), value, type);
      }
      else {
        builder.addAttribute(key, null, null, value, type);
      }
    }

    if (prefix == null) {
      builder.elementAttributesProcessed(name, prefix, defaultNamespace);
    }
    else {
      builder.elementAttributesProcessed(name, prefix, namespaces.getProperty(prefix));
    }

    if (ch == '/') {
      if (reader.read() != '>') {
        XMLUtil.errorExpectedInput(reader.getSystemID(), reader.getLineNr(), "`>'");
      }

      if (prefix == null) {
        builder.endElement(name, prefix, defaultNamespace);
      }
      else {
        builder.endElement(name, prefix, namespaces.getProperty(prefix));
      }

      return;
    }

    StringBuilder buffer = new StringBuilder(16);

    for (; ; ) {
      buffer.setLength(0);
      String str;

      for (; ; ) {
        XMLUtil.skipWhitespace(reader, buffer);
        str = XMLUtil.read(reader, '&');

        if ((str.charAt(0) == '&') && (str.charAt(1) != '#')) {
          XMLUtil.processEntity(str, reader, entityResolver);
        }
        else {
          break;
        }
      }

      if (str.charAt(0) == '<') {
        str = XMLUtil.read(reader, '\0');

        if (str.charAt(0) == '/') {
          XMLUtil.skipWhitespace(reader, null);
          str = XMLUtil.scanIdentifier(reader);

          if (!str.equals(fullName)) {
            XMLUtil.errorWrongClosingTag(reader.getSystemID(), reader.getLineNr(), name, str);
          }

          XMLUtil.skipWhitespace(reader, null);

          if (reader.read() != '>') {
            XMLUtil.errorClosingTagNotEmpty(reader.getSystemID(), reader.getLineNr());
          }

          if (prefix == null) {
            builder.endElement(name, prefix, defaultNamespace);
          }
          else {
            builder.endElement(name, prefix, namespaces.getProperty(prefix));
          }
          break;
        }
        else { // <[^/]
          reader.unread(str.charAt(0));
          scanSomeTag(true, //CDATA allowed
                           defaultNamespace, (Properties)namespaces.clone());
        }
      }
      else { // [^<]
        if (str.charAt(0) == '&') {
          ch = XMLUtil.processCharLiteral(str);
          buffer.append(ch);
        }
        else {
          reader.unread(str.charAt(0));
        }
        Reader r = new ContentReader(reader, entityResolver, buffer.toString());
        builder.addPCData(r, reader.getSystemID(), reader.getLineNr());
        r.close();
      }
    }
  }
private void processElement(String defaultNamespace, Properties namespaces)