@Override
    public void endElement(String uri, String localName, String qName) throws SAXException {

        if (CHOICE.equals(localName)) {
            inACChoiceDepth--;
        } else if (FALLBACK.equals(localName)) {
            inACFallbackDepth--;
        }
        if (inACChoiceDepth > 0) {
            return;
        }

        if (!includeTextBox && localName.equals(TEXTBOX)) {
            inTextBox = false;
            return;
        }
        if (PIC.equals(localName)) { //PIC_NS
            handlePict();
            inPic = false;
            return;
        } else if (RPR.equals(localName)) {
            inRPr = false;
        } else if (R.equals(localName)) {
            handleEndOfRun();
        } else if (T.equals(localName)) {
            inT = false;
        } else if (PPR.equals(localName)) {
            if (!pStarted) {
                bodyContentsHandler.startParagraph(currPProperties);
                pStarted = true;
            }
            currPProperties.reset();
        } else if (P.equals(localName)) {
            if (runBuffer.length() > 0) {
                //<p><tab></p>...this will treat that as if it were
                //a run...TODO: should we swallow whitespace that doesn't occur in a run?
                bodyContentsHandler.run(currRunProperties, runBuffer.toString());
                runBuffer.setLength(0);
            }
            pStarted = false;
            bodyContentsHandler.endParagraph();
        } else if (TC.equals(localName)) {
            bodyContentsHandler.endTableCell();
        } else if (TR.equals(localName)) {
            bodyContentsHandler.endTableRow();
        } else if (TBL.equals(localName)) {
            bodyContentsHandler.endTable();
        } else if (FLD.equals(localName)) {
            handleEndOfRun();
        } else if (DEL_TEXT.equals(localName)) {
            inDelText = false;
        } else if (INS.equals(localName) || DEL.equals(localName) || MOVE_TO.equals(localName) ||
                MOVE_FROM.equals(localName)) {
            editType = EditType.NONE;
        } else if (HYPERLINK.equals(localName)) {
            bodyContentsHandler.hyperlinkEnd();
        } else if (PICT.equals(localName)) {
            handlePict();
        } else if (V.equals(localName) && C_NS.equals(uri)) { // in value in a chart
            inV = false;
            handleEndOfRun();
        } else if (RT.equals(localName)) {
            inRt = false;
        } else if (RUBY.equals(localName)) {
            handleEndOfRuby();
        }
    }
This class is intended to handle anything that might contain IBodyElements:
main document, headers, footers, notes, slides, etc.
<p>
<p/>
<p>
This class does not generally check for namespaces, and it can be applied
to PPTX and DOCX for text extraction.
<p>
<p/>
This can be used to scrape content from charts.  It currently ignores
formula (&lt;c:f/&gt;) elements
<p>
<p/>
This does not work with .xlsx or .vsdx.
<p>
TODO: move this into POI?
tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-microsoft-module/src/main/java/org/apache/tika/parser/microsoft/ooxml/OOXMLWordAndPowerPointTextHandler.java