我目前正在尝试提出一个正则表达式来解析如下内容:
原始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>
个标记,不得触及。我只想在<p>...</p>
或<td>
内替换<th>
。
我还需要一个正则表达式来反转这个过程。请注意,这些正则表达式必须在VB / VBScript / Classic ASP中工作,所以虽然我可以使用lookaheads(我认为这是关键),但我不能使用lookbehinds。一些正在尝试失败的正则表达式是:
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>
任何想法(除了不用正则表达式做这个,哈哈)?
谢谢!
答案 0 :(得分:0)
正则表达式不适合像HTML这样的不规则语言。您最好使用正确的HTML解析器。
您可以使用PHP’s DOM library:
$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
}
答案 1 :(得分:0)
这是你的问题:
使用RegEx的一次拍摄必须有一些方法。
这是假的,没有办法。这在数学上是不可能的。正则表达式,即使是具有前瞻性的表达式,也无法维护解析HTML表达式所需的状态。
您必须使用HTML解析器。许多已经编写,如果您指定目标环境,我们可以帮助您选择一个。例如,在.Net中,HTML Agility Pack很好。
答案 2 :(得分:0)
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
可能不是最快的方式,也不是最好的方式,但它确实起到了作用。这是否有助于其他有类似问题的人,我不知道,但我认为我会抛弃这段代码以防万一,无论如何。