Мой анализатор RTF должен обрабатывать два вида файлов rtf (по одному файлу на выполнение программы): файлы rtf, сохраненные из Word, и файлы rtf, созданные утилитой генератора отчетов COTS.RTF для каждого действителен, но отличается.Мой анализатор использует шаблоны регулярных выражений для обнаружения, извлечения и обработки различных элементов rtf в двух типах файлов rtf.
Я решил реализовать список шаблонов регулярных выражений rtf в двух словарях, один для шаблонов регулярных выражений rtf.необходим для файла rtf Word и другого для шаблонов регулярных выражений rtf, необходимого для файла rtf утилиты COTS.Во время выполнения мой синтаксический анализатор определяет, какой тип файла RTF обрабатывается (Word RTF включает в себя элемент RTF //schemas.microsoft.com/office/word
, а COTS RTF - нет), а затем получает необходимый шаблон регулярных выражений из подходящего словаря.
Чтобы облегчить задачу ссылки на шаблоны при написании кода, я реализовал перечисление, где каждое значение перечисления представляет определенный шаблон регулярного выражения.Чтобы облегчить задачу синхронизации шаблонов с их соответствующими перечислениями, я реализовал шаблоны регулярных выражений в виде here-string
, где каждая строка представляет собой композицию csv: {enum name}, {word rtf regex pattern}, {cots rtf regex pattern}
.Затем, во время выполнения, когда шаблоны загружаются в их словари, я получаю значение int для enum из csv и использую его для создания ключа словаря.
Это облегчает написание кода, но я 'Я не уверен, что это лучший способ для реализации и ссылки на выражения RTF.Есть ли способ лучше?
Пример кода:
public enum Rex {FOO, BAR};
string ex = @"FOO, word rtf regex pattern for FOO, cots rtf regex pattern for FOO
BAR, word rtf regex pattern for BAR, cots rtf regex pattern for BAR
";
Я загружаю словари так:
using (StringReader reader = new StringReader(ex))
{
string line;
while ((line = reader.ReadLine()) != null)
{
string[] splitLine = line.Split(',');
int enumIntValue = (int)(Rex)Enum.Parse(typeof(Rex), splitLine[0].Trim());
ObjWordRtfDict.Add(enumIntValue, line.Split(',')[1].Trim());
ObjRtfDict.Add(enumIntValue, line.Split(',')[2].Trim());
}
}
Затем во время выполнения я получаю доступ к ObjWordRtfDict или ObjRtfDict в зависимости от типа rtf.файл, который анализатор обнаруживает.
string regExPattFoo = ObjRegExExpr.GetRegExPattern(ClsRegExExpr.Rex.FOO);
public string GetRegExPattern(Rex patternIndex)
{
string regExPattern = "";
if (isWordRtf)
{
ObjWordRtfDict.TryGetValue((int)patternIndex, out regExPattern);
}
else
{
ObjRtfDict.TryGetValue((int)patternIndex, out regExPattern);
}
return regExPattern;
}
Модифицированный Новый код, основанный на рекомендациях Асифа
Я сохранил свое перечисление для имен шаблонов, чтобы ссылки на имена шаблонов могли проверятьсякомпилятор
Пример CSV-файла, включенного в качестве встроенного ресурса
SECT,^\\pard.*\{\\rtlch.*\\sect\s\}, ^\\pard.*\\sect\s\}
HORZ_LINE2, \{\\pict.*\\pngblip, TBD
Пример использования
string sectPattern = ObjRegExExpr.GetRegExPattern(ClsRegExPatterns.Names.SECT);
Класс ClsRegExPatterns
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Text.RegularExpressions;
namespace foo
{
public class ClsRegExPatterns
{
readonly bool isWordRtf = false;
List<ClsPattern> objPatternList;
public enum Names { SECT, HORZ_LINE2 };
public class ClsPattern
{
public string Name { get; set; }
public string WordRtfRegex { get; set; }
public string COTSRtfRegex { get; set; }
}
public ClsRegExPatterns(StringBuilder rawRtfTextFromFile)
{
// determine if input file is Word rtf or not Word rtf
if ((Regex.Matches(rawRtfTextFromFile.ToString(), "//schemas.microsoft.com/office/word", RegexOptions.IgnoreCase)).Count == 1)
{
isWordRtf = true;
}
//read patterns from embedded content csv file
string patternsAsCsv = new StreamReader((Assembly.GetExecutingAssembly()).GetManifestResourceStream("eLabBannerLineTool.Packages.patterns.csv")).ReadToEnd();
//create list to hold patterns
objPatternList = new List<ClsPattern>();
//load pattern list
using (StringReader reader = new StringReader(patternsAsCsv))
{
string line;
while ((line = reader.ReadLine()) != null)
{
string[] splitLine = line.Split(',');
ClsPattern objPattern = new ClsPattern
{
Name = splitLine[0].Trim(),
WordRtfRegex = splitLine[1].Trim(),
COTSRtfRegex = splitLine[2].Trim()
};
objPatternList.Add(objPattern);
}
}
}
public string GetRegExPattern(Names patternIndex)
{
string regExPattern = "";
string patternName = patternIndex.ToString();
if (isWordRtf)
{
regExPattern = objPatternList.SingleOrDefault(x => x.Name == patternName)?.WordRtfRegex;
}
else
{
regExPattern = objPatternList.SingleOrDefault(x => x.Name == patternName)?.COTSRtfRegex;
}
return regExPattern;
}
}
}