private @Nullable String parseTagHeader(final boolean multipleRootTagError, final PsiBuilder.Marker tag) {
    if (multipleRootTagError) {
      final PsiBuilder.Marker error = mark();
      advance();
      error.error(XmlPsiBundle.message("xml.parsing.multiple.root.tags"));
    }
    else {
      advance();
    }

    final String tagName;
    if (token() != XML_NAME || myBuilder.rawLookup(-1) == TokenType.WHITE_SPACE) {
      error(XmlPsiBundle.message("xml.parsing.tag.name.expected"));
      tagName = "";
    }
    else {
      tagName = myBuilder.getTokenText();
      assert tagName != null;
      advance();
    }
    myTagNamesStack.push(tagName);

    do {
      final IElementType tt = token();
      if (tt == XML_NAME) {
        parseAttribute();
      }
      else if (tt == XML_CHAR_ENTITY_REF || tt == XML_ENTITY_REF_TOKEN) {
        parseReference();
      }
      else {
        break;
      }
    }
    while (true);

    if (token() == XML_EMPTY_ELEMENT_END) {
      advance();
      myTagNamesStack.pop();
      tag.done(XML_TAG);
      return null;
    }

    if (token() == XML_TAG_END) {
      advance();
    }
    else {
      error(XmlPsiBundle.message("xml.parsing.tag.start.is.not.closed"));
      myTagNamesStack.pop();
      tag.done(XML_TAG);
      return null;
    }

    if (myTagNamesStack.size() > BALANCING_DEPTH_THRESHOLD) {
      error(XmlPsiBundle.message("xml.parsing.way.too.unbalanced"));
      tag.done(XML_TAG);
      return null;
    }

    return tagName;
  }
private @Nullable String parseTagHeader(final boolean multipleRootTagError, final PsiBuilder.Marker tag)