1

I have an Email Service setup. It parses incoming email, gets all needed values and post them to proper fields in proper objects. Entire plain text body is saved. There is a chance that there will be no plain text body. So in this case I want to convert html to plain text. If someone know any open source code, it would be wonderful. External services are ok too, but I prefer to go with some custom logic.

Test class:

@isTest
private class HtmlToPlainTextConverter_UT {

  private static String validHtml = ''
    +'<!DOCTYPE html>'
    +'<html>'
    +'<head>'
      +'<title>Hi there</title>'
    +'</head>'
    +'<body>'
      +'This is a page</br>'
      +'a simple page'
      +'<table>'
      +'<tr>'
      +'<td>Col 1.1</td>'
      +'<td>Col 1.2</td>'
      +'</tr>'
      +'<tr>'
      +'<td>Col 2.1</td>'
      +'<td>Col 2.2</td>'
      +'</tr>'
      +'</table>'
    +'</body>'
    +'</html>'
  +'';

  private static String validConvertedHtml = ''
    +'Hi there\n'
    +'This is a page\n'
    +'a simple page\n'
    +'Col 1.1 Col 1.2 \n'
    +'Col 2.1 Col 2.2'
  +'';

  @isTest(SeeAllData=false)
  private static void validConvertTest() {
    System.assertEquals(validConvertedHtml, HtmlToPlainTextConverter.convert(validHtml));
  }
}

Converter's class:

/**
*
* @description Class contains methods for converting html to plain text
*
*
* @author Andrii Muzychuk
* @date 12/23/2014
*
*/
global class HtmlToPlainTextConverter {

  private static String anyOpenHtmlTag = '<\\W{0,1}\\w+\\s*\\w*>';

  // array is used to store order of patters
  private static String [] patternsApplyOrder = new String [] {
    '</td>',
    '</\\w+>',
    '</[h||H][0-9]{0,1}>',

    '<tr\\s*(valign=".{1,20}")*\\s*>',
    '<td\\s+colspan="[0-9]"\\s*>(\\s*||&nbsp;)\\s*</td>',
    '<td\\s*(style=".{1,40}")*\\s*>(\\s*||&nbsp;)\\s*</td>',

    anyOpenHtmlTag
  };

  private static Map<String, String> convertPatterns = new Map<String, String> {
    '</td>' => ' ',
    '</\\w+>' => '\n', // any closing tag convert to new line
    '</[h||H][0-9]{0,1}>' => '\n',

    '<tr\\s*(valign=".{1,20}")*\\s*>' => '\n',
    '<td\\s+colspan="[0-9]"\\s*>(\\s*||&nbsp;)\\s*</td>' => '\n --- \n',
    '<td\\s*(style=".{1,40}")*\\s*>(\\s*||&nbsp;)\\s*</td>' => '\t',

    anyOpenHtmlTag => ''
  };

  /**
  *
  * @description Method removes html tags or replaces them with line break
  *
  * @param htmlToConvert
  *
  *
  * @usage HtmlToPlainTextConverter.convert(htmlToConvert);
  *
  * @author Andrii Muzychuk
  * @date 12/23/2014
  *
  */
  global static String convert(String htmlToConvert) {
    String plainText = htmlToConvert;

    for (String convertPatternKey : patternsApplyOrder) {
        plainText = plainText.replaceAll(convertPatternKey, convertPatterns.get(convertPatternKey));
    }

    return plainText.trim();
  }

}
4

Use the String function stripHtmlTags() and it will do the work for you.

String1.stripHtmlTags()
| improve this answer | |
3

You could use pattern matching and regular expressions to strip out the HTML tags.
(Apex documentation on using patterns and matchers here.)

This pattern should match any HTML tag: <(?i).*?> (...I think!)

Deleting any text that matched that pattern would remove all the HTML tags, but it would also wipe out any line breaks. It would also leave you with missing spaces between words if you had something like this:

<li>Something to say</li><li>Something else to say</li>

I'm sure this isn't all-inclusive, but this is how I would start:

(1) Replace all <br> and <br/> tags with newLine characters \n

(2) Replace all text that matches the HTML tag pattern above with a single space. This would leave you with two spaces between some words, but would also solve the "missing spaces" problem I mentioned above.

(3) Replace all whitespace between words (i.e., one or more spaces) with a single space.

Something like this:

String myHTML = [your HTML email body here]    
String htmlPattern = '<(?i).*?>';
String breakPattern = '(?i)<br\s*/?>';  // matches <br>, <BR>, <br/>, <br />, <br   />, etc.
String whitespacePattern = '\\s+'

String workingText;
String plainText;

// replace all HTML break tags with the newLine character
pattern lineBreaks = pattern.compile(breakPattern);
matcher matchedLineBreaks = lineBreaks.matcher(myHTML);
workingText = matchedLineBreaks.replaceAll('\n');

// take what's left and remove all HTML tags, replacing them with a single space  
pattern htmlTags = pattern.compile(htmlPattern);
matcher matchedHTML = htmlTags.matcher(workingText);
workingText = matchedHTML.replaceAll(' ');

// replace all whitespace with single spaces, and we're all done!
pattern whitespace = pattern.compile(whitespacePattern);
matcher matchedWhitespace = whitespace.matcher(workingText);
plainText = matchedWhitespace.replaceAll(' ');  
| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.