问题
我正在寻找一种灵活的方法来解析电子邮件内容。以下是我正在处理的虚拟电子邮件文本示例。如果可能的话,我也想避免使用正则表达式。然而,在解决问题的过程中,我开始认为这是不可避免的。请注意,这只是完整电子邮件的一个小虚拟子集。我需要解析每个字段(例如,票号、手机)到它们各自的数据类型。最后,有些字段在电子邮件中可能不存在(您将在下面显示的当前解决方案中看到这是一个问题)。
Header Code:EMERGENCY
Ticket No: 123456789 Seq. No: 2
Update of:
Original Call Date: 01/02/2011 Time: 11:17:03 AM OP: 1102
Second Call Date: 01/02/2011 Time: 12:11:00 AM OP:
Company: COMPANY NAME
Contact: CONTACT NAME Contact Phone: (111)111-1111
Secondary Contact: SECONDARY CONTACT
Alternate Contact: Altern. Phone:
Best Time to Call: AFTER 4:30P Fax No: (111)111-1111
Cell Phone: Pager No:
Caller Address: 330 FOO
FOO AVENUE 123
当前解决方案
对于这个简单的示例,我成功地使用下面的函数解析了大多数字段。
private T BetweenOperation<T>(string emailBody, string start, string end)
{
var culture = StringComparison.InvariantCulture;
int startIndex =
emailBody.IndexOf(start, culture) + start.Length;
int endIndex =
emailBody.IndexOf(end, culture);
int length = endIndex - startIndex;
if (length < 0) return default(T);
return (T)Convert.ChangeType(
emailBody.Substring(startIndex, length).Trim(),
typeof(T));
}
基本上,我的想法是我可以解析两个字段之间的内容。例如,我可以通过执行以下操作获取标题代码:
// returns "EMERGENCY"
BetweenOperation<string>("email content", "Header Code:", "Ticket No:")
然而,这种方法有很多缺陷。其中一个大缺陷是end
字段并不总是存在。正如您所看到的,有一些具有相同关键字的类似键,但解析不正确,例如“联系人”和“次要联系人”。这会导致解析器获取过多的信息。此外,如果我的结束字段不存在,我将得到一些不可预测的结果。最后,我可以解析整行文本,然后使用此方法将其传递给BetweenOperation<T>
。
private string LineOperation(string startWithCriteria)
{
string[] emailLines = EmailBody.Split(new[] { '\n' });
return
emailLines.Where(emailLine => emailLine.StartsWith(startWithCriteria))
.FirstOrDefault();
}
我们在某些情况下会使用
LineOperation
,例如字段名不唯一(例如时间),并将结果馈送给BetweenOperation<T>
。问题:
如何基于关键字解析上述显示的内容。例如,“Header Code”和“Cell Phone”。请注意,我认为不能根据空格或制表符进行解析,因为某些字段可能有多行(例如来电者地址)或根本没有值(例如备用电话)。
谢谢。