@Override
    public void endElement(String namespaceURI, String localName, String qName)
            throws SAXException {
        if (BINARY_DATA.equals(localName)) {
            inBinaryData = false;
            try {
                processBinaryData();
            } catch (IOException e) {
                throw new SAXException(e);
            }
            return;
        }
        if (STYLE_NS.equals(namespaceURI) && "style".equals(localName)) {
            if (currTextStyle != null && currTextStyleName != null) {
                textStyleMap.put(currTextStyleName, currTextStyle);
                currTextStyleName = null;
                currTextStyle = null;
            } else if (currTextStyle != null && currParagraphStyleName != null) {
                paragraphTextStyleMap.put(currParagraphStyleName, currTextStyle);
                currParagraphStyleName = null;
                currTextStyle = null;
            }
        } else if (TEXT_NS.equals(namespaceURI) && "list-style".equals(localName)) {
            listStyle = null;
        }

        // call next handler if no filtering
        if (completelyFiltered == 0) {
            // special handling of text:h, that are directly passed
            // to incoming handler
            if (TEXT_NS.equals(namespaceURI) && "h".equals(localName)) {
                final String el = headingStack.pop();
                closeStyleTags();
                handler.endElement(namespaceURI, el, el);
            } else if (TEXT_NS.equals(namespaceURI) && "list".equals(localName)) {
                endList();
            } else if (TEXT_NS.equals(namespaceURI) && "span".equals(localName)) {
                currTextStyle = null;
                hasWrittenStartStyleTags = false;
            } else if (TEXT_NS.equals(namespaceURI) && "p".equals(localName)) {
                endParagraph();
            } else if ("annotation".equals(localName) || "note".equals(localName) ||
                    "notes".equals(localName)) {
                closeStyleTags();
                handler.endElement(namespaceURI, "p", "p");
            } else if ("a".equals(localName)) {
                closeStyleTags();
                super.endElement(namespaceURI, localName, qName);
            } else {
                super.endElement(namespaceURI, localName, qName);
            }

            // special handling of tabulators
            if (TEXT_NS.equals(namespaceURI) &&
                    ("tab-stop".equals(localName) || "tab".equals(localName))) {
                this.characters(TAB, 0, TAB.length);
            }
        }

        // revert filter for *all* content of some tags
        if (needsCompleteFiltering(namespaceURI, localName)) {
            completelyFiltered--;
        }
        assert completelyFiltered >= 0;

        // reduce current node depth
        nodeDepth--;
        assert nodeDepth >= 0;
    }
Check if a node is a text node
tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-miscoffice-module/src/main/java/org/apache/tika/parser/odf/OpenDocumentBodyHandler.java