public void flushCharacters(boolean finalFlush, boolean topLevel) throws SAXException {

    if (currentCharacters.length() > 0) {

      final String currentString = currentCharacters.toString();
      final char[] chars = currentString.toCharArray();
      if (StringUtils.isBlank(currentString) || !topLevel) {
        // Just output whitespace as is
        super.characters(chars, 0, chars.length);
      } else {

        // The first element received determines the type of separator
        checkDelimiters(XMLConstants.XHTML_NAMESPACE_URI, spanQName, topLevel);

        // Wrap any other text within an xhtml:span
        super.startElement(
            XMLConstants.XHTML_NAMESPACE_URI,
            "span",
            spanQName,
            getAttributesWithClass(XMLUtils.EMPTY_ATTRIBUTES));
        super.characters(chars, 0, chars.length);
        super.endElement(XMLConstants.XHTML_NAMESPACE_URI, "span", spanQName);
      }

      isCharacters = false;
      currentCharacters.setLength(0);
    }

    if (finalFlush) checkDelimiters(XMLConstants.XHTML_NAMESPACE_URI, spanQName, topLevel);
  }
  public void flushCharacters(boolean finalFlush, boolean topLevelCharacters) throws SAXException {

    final String currentString = currentCharacters.toString();

    if (topLevelCharacters && !isAroundTableOrListElement) {
      // We handle top-level characters specially and wrap them in a span so we can hide them
      generateTopLevelSpanWithCharacters(currentCharacters.toString());
    } else {
      // Just output characters as is in deeper levels, or when around at table or list element
      final char[] chars = currentString.toCharArray();
      super.characters(chars, 0, chars.length);
    }

    currentCharacters.setLength(0);

    if (finalFlush) generateFirstDelimitersIfNeeded();
  }