1

Apologies for the poor formatting; first time poster.

I'm working with an InboundEmail object being sent it from a form from one of our internal systems - it's basically just sending an HTML email into Salesforce. We want to get the answers that have been provided on the form, and RegEx is the way we're trying to do it. Here's a snippit of the HTML coming into Salesforce:

                        <td><img src="/images/spacer.gif" width="10" height="1"></td>
                        <td><span style="color:;"><b>Description of Incident</b></span></td>
                    </tr>

                    <tr>
                        <td colspan="3"><img src="/images/spacer.gif" width="1" height="5"></td>
                    </tr>
                    <tr>                
                        <td colspan="2"><img src="/images/spacer.gif" width="10" height="1"></td>
                        <td style="width:100%">The incident failed for no good reason.</td>
                    </tr>
                    <tr>
                        <td colspan="3"><img src="/images/spacer.gif" width="1" height="15"></td>
                    </tr>

In the above example, the question is Description of incident and the answer is The incident failed for no good reason. So the RegEx pattern we're using is the following:

Desc((.|\n)?)%.

This will get us everything from the word Desc right up to the tag beside the answer. I've tested this in RegEx builders and can confirm this is the case.

So here's the APEX code I'm using in Salesforce, this gets triggered when an email is sent into SF:

String descriptionRegex = 'Desc((.|\n)?)%.'; String extracteddescription = ''; String finaldescription = ''; Pattern descriptionPattern = Pattern.compile(descriptionRegex); Matcher descriptionMatcher = descriptionPattern.matcher(email.htmlBody);

if (descriptionMatcher.matches()) {

System.debug('Found a match'); extractedDescription = descriptionMatcher.group(0); System.debug('Group extract: ' + extracteddescription); System.debug('index of percentage: ' + extracteddescription.indexOf('%')); System.debug('index of less than: ' + wxtracteddescription.lastIndexOf('<'));

finaldescription = extracteddescription.substring((extracteddescription.indexOf('%') + 3), extracteddescription.lastIndexOf('<')); System.debug('Final description: ' + finaldescription); } else { System.debug('Did not find a match'); }

Expected result

With the above code, I'm getting the block of text (previously confirmed that I should be returning using the above Pattern), if I've found a match, then extract the answer using a String.substring method.

Actual result

When the code runs, I hit the else condition, and no pattern is matched.

Any idea why my code isn't working?

Also some supplementary information; the htmlBody variable is returning the HTML of the email. I've put said variable result into a debug statement, and ran the output HTML against my RegEx and can confirm it should be picked up

  • 1
    I suggest you try executing stripHtmlTags(email.htmlBody) and assigning it to a new string variable before running your pattern matcher to see if that doesn't solve your problems. – crmprogdev Jun 3 '15 at 20:16
  • 1
    @crmprogdev It's a good shout but without any HTML to hang on to I can't really tell what text is the answer we're seeking. – bengrah Jun 4 '15 at 10:33
  • I just noticed that as you've written it now, your RegEx pattern doesn't work at all for me when I try using it at regexr.com, a site that's always been very reliable for me. I even pasted your entire HTML code from above into the end of what they have to test against. – crmprogdev Jun 4 '15 at 13:43
1

Don't worry, you've got 100 problems now.

I had a problem with regex's where there were multiple lines for the regex to parse.

For example, I have two strings:

  1. 'hello'
  2. '123\nhello'

Matching .*ell.* will come back fine on the first string, but not the second.

Meet single line and multi line modifers: (?ms)

(?ms).*ell.* will now match on that second string.

Proof:

Try doing this in developer console, and check the output:

String input = '123\nhello';
Pattern p1 = Pattern.compile('.*ell.*');
Pattern p2 = Pattern.compile('(?ms).*ell.*');
system.debug(p1.matcher(input).matches());
system.debug(p2.matcher(input).matches());
  • Hi Ben. getting a little bit further using your example. But still running into a similar problem. So expanding on your example, here's the string I'm using: 123\nhello\n456\nare you there\ngoodbye\ngoodbye I want a pattern that starts at 456, up until the first instance of the word 'goodbye', so I've used the following pattern: (?ms)456.*are(.*?)goodbye – bengrah Jun 4 '15 at 11:13
  • So it's a multiline pattern, where dots are considered any and new line characters. Start at the phrase '456' and gobble up all text until the phrase 'are', then after that, gobble up any text until the first instance of the word 'goodbye' Testing this pattern in Sublime works just as it should, I've put the following code into the Anonymous Code console window - see next comment – bengrah Jun 4 '15 at 11:14
  • String input = '123\nhello\n456\nare you there\ngoodbye\ngoodbye'; Pattern p1 = Pattern.compile('.*ell.*'); Pattern p2 = Pattern.compile('(?ms)456.*are(.*?)goodbye'); system.debug(p1.matcher(input).matches()); system.debug(p2.matcher(input).matches()); The code runs, but I still get two FALSE matches. I'm really not sure where I'm going wrong here. – bengrah Jun 4 '15 at 11:14
  • I think your regex isn't doing what you think it is. I would use this pattern: (?ms).*456(.*)goodbye.* for your pattern. Gives me a match on the string you are looking for and returns \nare you there\ngoodbye\n. If you want to get rid of that goodbye from the return, you need to exclude it from the (.*) back reference group. – Ben Naylor Jun 4 '15 at 23:09
0

In the end we used a different method in order to get at the data we wanted, we used the find() (link) which returned the results that we expected. Before we were trying to use match() (link) which tries to match the pattern against the entire string - I'm still pretty sure what we were trying to do falls under this remit however.

As recommended by Salesforce Support to us, the find() method attempts to find the next subsequence of the input sequence that matches the pattern. This method returns true if a subsequence of the input sequence matches this Matcher object's pattern. which does seem more specific to our case.

Thank you for your help on this.

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.