Удаление неполных P-тегов (используя REGEX или любой другой метод) - PullRequest
0 голосов
/ 21 сентября 2010

мои проблемы немного зависят от конкретного случая,

прежде всего

Это только для <p> тегов, а не для любых других тегов. Так что вам не нужно беспокоиться о любом другом теге.

У меня есть HTML-документ, который является выходом одного программного обеспечения, но в нем есть некоторые ошибки, такие как незамкнутые <p> теги.

например. Я взял весь документ в строку

мой документ похож ..

    <html>
    ....
    ....
      <head>
      </head>
    ....
    ....
       <body>

    ...
    ...
    <p>                 // tag is to be removed as no closing tag

<p align="left">   AAA   </p>
<p class="style6">   BBB    </P>
<p class="style1" align="center">    CCC    </P>

<p align="left">  DDD               // tag is to be removed as no closing tag
<p class="style6">   EEE              // tag is to be removed as no closing tag
<p class="style1" align="center">    FFF             // tag is to be removed as no closing tag

<p class="style15"><strong>xxyyzz</strong><br/></p>

<p>                // tag is to be removed as no closing tag



<p> stack Overflow </P>


       <body>
      </html>

теги с DDD, EEE, FFF и незамкнутый тег <p> должны быть удалены Как видите, он должен работать для каждого незамкнутого тега <P>, независимо от того, имеет ли он атрибуты, такие как class или align.

Я также хочу отметить, что внутри другого тега <p> нет тега <p>, я имею в виду

<p>
    <p>
    </p>

     <p>
     </p>

</p>

Такое состояние никогда не возникнет.

Я пытался использовать REGEX и StringBuilder, но не смог получить идеальный ответ.

Заранее большое спасибо тем, кто поможет.

Привет

Ответы [ 4 ]

1 голос
/ 22 сентября 2010

Я очень ценю помощь от всех вас, особенно JIM и ALEX. Я пытался, и это работает хорошо. спасибо много.

 public static string CleanUpXHTML(string xhtml)
            {
                int pOpen = 0, pClose = 0, pSlash = 0, pNext = 0, length = 0;
                pOpen = xhtml.IndexOf("<p", 0);
                pClose = xhtml.IndexOf(">", pOpen);
                pSlash = xhtml.IndexOf("</p>", pClose);
                pNext = xhtml.IndexOf("<p", pClose);

                while (pSlash > -1)
                {


                    if (pSlash < pNext)
                    {
                        if (pSlash < pNext)
                        {
                            pOpen = pNext;
                            pClose = xhtml.IndexOf(">", pOpen);
                            pSlash = xhtml.IndexOf("</p>", pClose);
                            pNext = xhtml.IndexOf("<p", pClose);
                        }
                    }
                    else
                    {
                        length = pClose - pOpen + 1;
                        if (pNext < 0 && pSlash > 0)
                        {
                            break;
                        }


                        xhtml = xhtml.Remove(pOpen, length);

                        pOpen = pNext - length;
                        pClose = xhtml.IndexOf(">", pOpen);
                        pSlash = xhtml.IndexOf("</p>", pClose);
                        pNext = xhtml.IndexOf("<p", pClose);


                    }

                    if (pSlash < 0)
                    {
                        int lastp = 0, lastclosep = 0, lastnextp = 0, length3 = 0, TpSlash =0 ;

                        lastp = xhtml.IndexOf("<p",pOpen-1);

                        lastclosep = xhtml.IndexOf(">", lastp);
                        lastnextp = xhtml.IndexOf("<p", lastclosep);


                        while (lastp >0)
                        {
                            length3 = lastclosep - lastp + 1;
                            xhtml = xhtml.Remove(lastp, length3);
                            if (lastnextp < 0)
                            {
                                break;
                            }
                            lastp = lastnextp-length3;
                            lastclosep = xhtml.IndexOf(">", lastp);
                            lastnextp = xhtml.IndexOf("<p", lastclosep);

                        }

                        break;
                    }

                }

                return xhtml;

            }
1 голос
/ 21 сентября 2010

Отказ от ответственности: обратите внимание, что я не защищаю попытки разбора произвольного HTML с помощью регулярных выражений или простых совпадений подстрок. Приведенное ниже решение предназначено для этой конкретной проблемы , которая, как представляется, намеренно ограничена, чтобы сделать возможным анализ с помощью простых методов. В общем, я согласен с консенсусом: для разбора HTML используйте HTML-парсер.

Это сказал. , .

Учитывая, что вложенные теги <p> не разрешены, и при условии, что HTML-комментарии не разрешены, в цикле должно быть относительно легко выполнить следующее, чтобы найти и удалить все теги <p>, которые имеют нет соответствующих </p>.

string inputText = GetHtmlText();
int scanPos = 0;
int startTag = inputText.IndexOf("<p>", scanPos);
while (startTag != -1)
{
    scanPos += 4;
    // Now look for a closing tag or another open tag
    int closeTag = inputText.IndexOf("</p">, scanPos);
    int nextStartTag = inputText.IndexOf("<p>", scanPos);
    if (closeTag == -1 || nextStartTag < closeTag)
    {
        // Error at position startTag.  No closing tag.
    }
    else
    {
        // You have a full paragraph between startTag and (closeTag+5).
    }
    startTag = nextStartTag;
}

Код предполагает, что строки <p> и </p> не могут существовать в тексте, за исключением фактических открытых и закрывающих тегов абзаца. Если вы можете сделать эту гарантию, то вышеприведенное (или что-то очень похожее) должно работать довольно хорошо.

ДОБАВЛЕНО:

Работа с такими вещами, как <p class="classname"> и т. Д., Становится немного менее уверенной. Если вы можете гарантировать, что между открывающим <p и закрывающим > не будет никаких символов >, вы можете изменить приведенный выше код для поиска <p, а также <p>, и если найдено, найдите закрывающий >. Это немного грязно, но не особенно сложно.

При всем том, что я сказал, я бы не рекомендовал этот подход для анализа произвольного HTML из-за оговорок, о которых я уже говорил: он не будет обрабатывать комментарии и делает, вероятно, неверные предположения о формате HTML в целом. , Он также не будет обрабатывать такие вещи, как <p > и </p >, оба из которых являются совершенно действительными (и с которыми я столкнулся в дикой природе).

1 голос
/ 21 сентября 2010

Вы можете получить лучшие результаты, используя Html Agility Pack :

Это библиотека кода .NET, которая позволяет вам разобрать "вне интернета" HTML файлы. Парсер очень терпимый с "реальным миром" искаженным HTML. объектная модель очень похожа на то, что предлагает System.Xml, но для HTML.

Просто загрузите документ в DOM, итерируйте по элементам, ищущим <p>, и отфильтруйте их, почти как вы делали правильные манипуляции с XML.

0 голосов
/ 21 сентября 2010

Прежде всего, пожалуйста, посмотрите здесь . Если это не помешало вам использовать регулярные выражения для парсинга HTML (и потому, что я понимаю, что это очень специфический случай, который может не оправдать использование полного парсера DOM, даже если это абсолютно лучший рекомендуемый способ), я отправил ответ на похожий вопрос здесь ; Вы можете легко адаптировать его для своего случая, но, пожалуйста, поймите, что это не рекомендуется, и многие вещи могут пойти не так, если вы решите его использовать (включая, как указано в первой ссылке выше, конец вселенной и т. д.: P).

Если регулярное выражение, на которое я указывал, кажется вам слишком сложным или у вас возникли проблемы с пониманием или упрощением, оставьте комментарий, и я добавлю больше пояснений.

...