Выражение Regex и c # - PullRequest
       12

Выражение Regex и c #

2 голосов
/ 17 ноября 2011

У меня проблема с методом обработки строк, который я написал. Целью этого метода является поиск тегов ссылок в длинной строке и переформатирование их ссылок.

Чтобы дать некоторый контекст, я анализирую большое количество файлов 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
  &amp; fingers forward, and put 2nd <strong><a href="../f/fist_hand.html">FIST</a></strong> hand, back forward
  &amp; 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 &amp; 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 &amp; 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 &amp; fingers forward, and put 2nd <strong><a href="/pages/displayc.aspx?c=dictionary&alpha=f&sign=fist">FIST</a></strong> hand, back forward &amp; 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;
    }

Ответы [ 2 ]

1 голос
/ 17 ноября 2011

Я рекомендую попробовать HTML Agility Pack для анализа и запроса ваших документов HTML.

Использование RegEx может быть довольно хрупким, и, если документы не очень однородны, может быть подход, который не будет работать - см. этот ответ SO .

0 голосов
/ 17 ноября 2011

В дополнение к ответу @ Oded вы можете сделать это с помощью простого XSL-преобразования. Regex IMO - это не тот путь, по которому можно идти.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...