code: public void endElement(String namespaceURI, String localName,
                             String qName) throws SAXException {
          trace("endElement:" + localName + "~" + qName);
          if (currentElement==null) {
              warn(qName + ": endElement before any startElement");
              return;
          }
  
          Node parentNode;
          boolean atDocumentRoot = false, foundTagToEnd = false;
          Element startElement = currentElement;
  
          while (!(foundTagToEnd || atDocumentRoot)) {
              parentNode = currentElement.getParentNode();
  
              if (parentNode.getNodeType()==Node.ELEMENT_NODE) {
                  foundTagToEnd = isElementMatching(currentElement, qName);
                  currentElement = (Element) parentNode;
              } else if (parentNode.getNodeType()==Node.DOCUMENT_NODE) {
                  atDocumentRoot = true;
                  if (startElement==currentDocument.getDocumentElement()) {
                      foundTagToEnd = isElementMatching(startElement, qName);
                  } else {
                      currentElement = startElement;
                  }
              } else {
                  throw new IllegalArgumentException("Closing element " + qName
                                                     + ": expecting a parent ELEMENT_NODE but found " + parentNode);
              }
          }
          if (!foundTagToEnd) {
              warn(qName + ": endElement does not match startElement!");
          }
      }
docs: ContentHandler method
  @throws SAXException