删除不完整的P标签(使用REGEX或任何其他方法)

时间:2010-09-21 14:24:09

标签: c# .net regex visual-studio parsing

我的问题有点具体,

首先,

仅适用于<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>标记,无论它是否具有类或对齐等属性。

我还想提一下,另一个<p>标记内没有<p>标记,我的意思是

<p>
    <p>
    </p>

     <p>
     </p>

</p>

这种情况永远不会发生。

我尝试使用REGEX和StringBuilder但无法得到完美答案。

对于那些愿意帮助的人来说,提前做了很多。

此致

4 个答案:

答案 0 :(得分:1)

使用 Html Agility Pack

可能会获得更好的结果
  

这是一个允许的.NET代码库   你解析“out of the web”HTML   文件。 解析器非常宽容   与“现实世界”格式错误的HTML。   对象模型非常类似于什么   提出了System.Xml,但是对于HTML。

只需将文档加载到DOM中,遍历查找<p>的元素并过滤掉它们,就像您正在进行有效的XML操作一样。

答案 1 :(得分:1)

免责声明:请注意,我不主张尝试使用正则表达式或简单子字符串匹配来解析任意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 >这样的东西,它们都是完全有效的(我在野外遇到过)。

答案 2 :(得分:1)

我非常感谢你们所有人的帮助,尤其是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;

            }

答案 3 :(得分:0)

首先,请看一下here。如果这并没有阻止你使用正则表达式来解析HTML(并且因为我理解它是一个非常具体的情况,可能无法保证使用完整的DOM解析器,即使这是绝对最好的推荐方式),我已经发布了答案类似的问题here;您可以轻松地根据您的情况调整它,但请理解不推荐使用它,如果您决定使用它,很多事情都可能出错(包括,如上面第一个链接中所述,宇宙结束等等:P)。

如果我指向你的正则表达式看起来太复杂或者您在理解或简化它时遇到了问题,请发表评论,我会添加更多说明。