У меня проблема с методом обработки строк, который я написал. Целью этого метода является поиск тегов ссылок в длинной строке и переформатирование их ссылок.
Чтобы дать некоторый контекст, я анализирую большое количество файлов HTML, которые были на компакт-диске, и сопоставляю результаты с файлами XML, которые находятся на веб-сайте в отдельном проекте (я написал это как часть консольного приложения) , HTML-файлы содержат учебный текст, и он содержит ссылки, относящиеся к файлам на компакт-диске, и мне нужно изменить hrefs, чтобы они относились к веб-сайту, на котором происходит информация.
Следующий код работает нормально, если есть только один тег ссылки, но пропустите его два, и результат будет очень испорчен. Как ни странно, редактор регулярных выражений Visual Studio утверждает, что приведенное ниже регулярное выражение linkTag соответствует только тегам ссылок, но когда дело доходит до замены ссылок на правильные hrefs, он вставляет фрагменты ссылок в различных точках в строке инструкции.
Причина дополнительного регулярного выражения alphaDir заключается в том, что я в конечном итоге расширю этот метод, чтобы исправить ссылки с различными начальными hrefs. Мы говорим о разборе тысяч html-файлов, но этот формат является наиболее распространенным.
Я немного растерялся из-за этого, так как я в значительной степени новичок в области регулярных выражений, и написал все регулярные выражения ниже себя, так что любые мысли по любому из них тоже были бы хорошими.
Типичная строка ввода
Hold 1st <strong><a href="../f/fist_hand.html">FIST</a></strong> hand, back outward
& fingers forward, and put 2nd <strong><a href="../f/fist_hand.html">FIST</a></strong> hand, back forward
& fingers inward, with lower knuckle of its 4th finger on
lower knuckle of 1st thumb; then slide 2nd hand forwards one
hand's length.
Метод
static string instructions(string instructions)
{
Regex Spaces = new Regex(@"\s+|\n|\r");
Regex linkTag = new Regex(@"<a(.*?)>(.*?)<\/a>");
Regex linkTagHtml = new Regex(@"<a(.*?)>|<\/a>");
Regex hrefAttr = new Regex("href=\"(.)*?\"");
Regex alphaDir = new Regex(@"/([a-z])?/");
string signName = string.Empty;
char alphaChar;
string replacementLinkTag = string.Empty;
string replacementHref = string.Empty;
instructions = Spaces.Replace(instructions, " ");
MatchCollection matches = linkTag.Matches(instructions);
foreach (Match link in matches)
{
Match alphaDirMatch = alphaDir.Match(link.Value.ToString());
if (alphaDirMatch.Success)
{
Match hrefAttrMatch = hrefAttr.Match(link.Value.ToString());
if (hrefAttrMatch.Success)
{
signName = linkTagHtml.Replace(link.Value.ToString(), string.Empty).ToLower().Trim();
signName = signName.Replace(" ", "_");
alphaChar = signName[0];
replacementHref = "href=\"/pages/displayc.aspx?c=dictionary&alpha=" + alphaChar.ToString() +"&sign=" + signName + "\"";
replacementLinkTag = hrefAttr.Replace(link.Value.ToString(), replacementHref);
instructions = instructions.Remove(link.Index, link.Length);
instructions = instructions.Insert(link.Index, replacementLinkTag);
}
}
}
return instructions;
}
Текущая строка вывода
Hold 1st <strong><a href="/pages/displayc.aspx?c=dictionary&alpha=f&sign=fist">FIST</a></strong> hand, back outward & finge<a href="/pages/displayc.aspx?c=dictionary&alpha=f&sign=fist">FIST</a>f="../f/fist_hand.html">FIST</a></strong> hand, back forward & fingers inward, with lower knuckle of its 4th finger on lower knuckle of 1st thumb; then slide 2nd hand forwards one hand's length.
Желаемая строка вывода
Hold 1st <strong><a href="/pages/displayc.aspx?c=dictionary&alpha=f&sign=fist">FIST</a></strong> hand, back outward & fingers forward, and put 2nd <strong><a href="/pages/displayc.aspx?c=dictionary&alpha=f&sign=fist">FIST</a></strong> hand, back forward & fingers inward, with lower knuckle of its 4th finger on lower knuckle of 1st thumb; then slide 2nd hand forwards one hand's length.
Решение - Спасибо за предложение Одед!
Я использовал HtmlAgilityPack для загрузки строки инструкций в виде html и нашел теги ссылок, сохраняющие их в HtmlNodeCollection, циклически перебирая все и получая значения href и выполняя правки.
Код для тех, кто заинтересован, выглядит так:
static string instructions(string instructions)
{
char alphaChar;
Regex Spaces = new Regex(@"\s+|\n|\r");
Regex alphaDir = new Regex(@"/([a-z])?/");
string signName = string.Empty;
string replacementHref = string.Empty;
instructions = Spaces.Replace(instructions, " ");
HtmlDocument instr = new HtmlDocument();
instr.LoadHtml(instructions);
HtmlNodeCollection links = instr.DocumentNode.SelectNodes("//a");
if (links != null)
{
foreach (HtmlNode link in links)
{
string href = link.GetAttributeValue("href", string.Empty);
if (!string.IsNullOrWhiteSpace(href))
{
Match alphaDirMatch = alphaDir.Match(href);
if (alphaDirMatch.Success)
{
signName = Regex.Replace(href, "(.)*?/([a-z])?/|(.html)?", string.Empty);
signName = signName.Replace(" ", "_");
alphaChar = signName[0];
replacementHref = "/pages/displayc.aspx?c=dictionary&alpha=" + alphaChar.ToString() + "&sign=" + signName;
link.SetAttributeValue("href", replacementHref);
}
}
}
}
instructions = instr.DocumentNode.InnerHtml.ToString();
return instructions;
}