繁体   English   中英

用于解析HTML段的正则表达式(regex)

[英]Regular Expression (regex) to Parse HTML Segment

我目前正在尝试提出一个正则表达式,它将解析如下内容:

原始HTML:

<td align="center"><p>line 1</p><p>line 2</p><p>line 3</p></td>

预期的HTML:

<td align="center">line 1<br />line 2<br />line 3</td>

请注意,整个HTML文档中还有其他<p>...</p>标签,这些标签不能被触摸。 我只想在<td><th>替换<p>...</p>

我还需要一个正则表达式来逆转该过程。 请注意,这些正则表达式必须在VB / VBScript / Classic ASP中起作用,因此尽管我可以使用前行(我认为这是此处的关键),但不能使用后行。 我尝试失败的一些正则表达式是:

1. <td[^>]*>(<p>.+<\/p>)<\/td>
2. <td[^>]*>(<p>.+<\/p>)+?<\/td>
3. <td[^>]*><p>(?:(.+?)<\/p><p>(.+))+<\/p><\/td>
4. <td[^>]*>(<p>(?:(?!<\/p>)).*<\/p>)+?<\/td>
5. <td[^>]*>(?:<p>(.+?)<\/p>)*(?:<p>(.+)<\/p>)<\/td>
6. <td[^>]*>(?:<p>(.+?)<\/p>)(?:<p>(.+)<\/p>)*(?:<p>(.+)<\/p>)<\/td>

我可以“欺骗”并拉出整行,然后通常使用标准的VB字符串操作函数手动对其进行解析,但这绝对不是最优雅的方法,也不是最快的方法。 必须使用某种方式使用RegEx一次完成此操作。

最终我想服用...

<td align="center"><p><span style="color:#ff0000;"><strong>line 1</strong></span></p><p>line 2</p><p>line 3</p></td>

...然后变成

<td align="center"><span style="color:#ff0000;"><strong>line 1</strong></span><br />line 2<br />line 3</td>

有什么想法(除了不要使用正则表达式,大声笑)?

谢谢!

正则表达式不适用于HTML之类的不规则语言。 您最好使用适当的HTML解析器。

您可以使用PHP的DOM库

$doc = new DOMDocument();
$doc->loadHTML($code);
$xpath = new DOMXpath($doc);
forach ($xpath->query('//td/p') as $i => $elem) {  // find all P elements that are a child of a TD
    if ($i != 0) {                                  // add BR for any P except the first
        $elem->parentNode->insertBefore($doc->createElement('br'), $elem);
    }
    foreach ($elem->childNodes as $nodes) {        // move contents out of P
        $elem->parentNode->insertBefore($node, $elem);
    }
    $elem->parentNode->removeChild($elem);         // remove empty P
}

这是您的问题:

必须使用某种方式使用RegEx一次完成此操作。

这是错误的,没有办法。 从数学上讲这是不可能的。 正则表达式,即使具有前瞻性的正则表达式也无法维持解析HTML表达式所需的状态。

您必须使用HTML解析器。 已经写了很多,如果您指定目标环境,我们可以帮助您选择一个。 例如,在.Net中,HTML Agility Pack很不错。

更具体地说,ASP和IIS确实支持ISAPI筛选器,但是,我不想或不必求助于它。 HTML段只是一个字符串,不是DOM树的一部分(尽管我可以将其转换为一个)。

最终,这是我解决问题的方法,因为正则表达式显然不能满足我的要求:

RE3.Pattern = "<td[^>]*><p>.+?<\/p><\/td>"
Set Matches = RE3.Execute(it)
If Matches.Count > 0 Then
   RE3.Pattern = "<p[^>]*>"
   For Each Match In Matches
      itxt_tmp = Replace(Replace(RE3.Replace(Match.Value,""),"</p>","<br />"),"<br /></td>","</td>")
      it = Replace(it,Match.Value,itxt_tmp)
   Next
End If
Set Matches = Nothing

并回到原始的:

RE.Pattern = "<td[^>]*>.+?<\/td>"
Set Matches = RE.Execute(itxt)
If Matches.Count > 0 Then
   For Each Match In Matches
      If InStr(1,Match.Value,"<br />") > 1 Then
         RE.Pattern = "<td([^>]*)>"
         itxt_tmp = RE.Replace(Replace(Replace(Match.Value,"<br />","</p><p>"),"</td>","</p></td>"),"<td$1><p>")
         itxt = Replace(itxt,Match.Value,itxt_tmp)
      End If
   Next
End If
Set Matches = Nothing

可能不是最快的方法,也不是最好的方法,但是它确实起作用。 我不知道这是否对遇到类似问题的人有帮助,但我想我还是把这个代码段扔了出去,以防万一。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM