正则表达式用于解析HTML表?

时间:2019-11-18 20:02:30

标签: java html regex

我已经尝试了很多不同的正则表达式,但是找不到解决方案。

我需要一个正则表达式来找到:

<tr>
    <td>XYZ</td>
    <td>XYZ</td>
</tr>
<tr>
    <td>XYZ</td>
</tr>
<tr>
    <td>XYZ</td>
</tr>

这是我到目前为止所拥有的:

<tr>\s*<td.*?>(.*?)</td>\s*<td.*?>(.*?)</td>\s*</tr>(\s*<tr>\s*<td>.*?</td>\s*</tr>)*

因此,第一个<tr>块必须包含两个<td>标签,所有随后的(0个或多个)<tr>标签必须仅包含1个<td>标签。

非常感谢。

2 个答案:

答案 0 :(得分:-1)

这是用于从网页源代码提取HTML表的正则表达式格式:

(?is)<tr.*?>.*?(?:<td.*?>(.*?)<\/td>\s*)(?=(?:<td.*?>(.*?)<\/td>)?).*?<\/tr>

您可以在任何编程语言中应用以上格式。这取决于所用语言处理正则表达式的方式。

答案 1 :(得分:-1)

使用正则表达式处理HTML标签是有问题的;如果可能的话,应该使用HTML解析。让我们以识别(虚构)标签<a><b>的简单情况为例。为了简单起见,我们将假定我们不必担心这些标记或空白上的属性。我们对识别嵌套在<b>标签中的单个<a>标签感兴趣,例如:

<a><b>1</b></a>

“明显”但不正确的正则表达式为:

<a><b>.*?</b></a>

它将与上面的示例匹配,但也将匹配:

<a><b>1</b><b>2</b></a>

即使.*?不是 greedy ,它也要尽可能地贪婪,以使其余的输入与正则表达式的其余部分匹配。

您需要将.*?替换为不会扫描结束</b>标签的内容:

((?!</b>).)*

这表示只要下一个字符不是结束</b>标记,就再扫描一个字符。作为一项很好的措施,您可能还希望确保不要跳过另一个<a>标签的开头:

((?!(<a>|</b>)).)*

因此最终的正则表达式变为:

<a><b>((?!(<a>|</b>)).)*</b></a>

无论如何,这就是我所采用的方法。因此,针对当前问题的正则表达式变得相当复杂。

我的理解是,您正在寻找带有两个嵌套<tr>标签的<td>标签,然后是带有一个嵌套<tr>标签的0个或多个<td>标签。如果我有那条直线,则正则表达式为:

"(?s)<tr[^>]*>(\\s*<td[^>]*>((?!(<tr|</td)).)*</td>\\s*){2}\\s*</tr>(\\s*<tr[^>]*>\\s*<td[^>]*>((?!(<tr|</td)).)*</td>\\s*</tr>)*"

代码:

import java.util.regex.Pattern;
import java.util.regex.Matcher;
import java.util.regex.MatchResult;

public class Test
{
    public static void doMatch (String s) {
        Pattern pattern = Pattern.compile("(?s)<tr[^>]*>(\\s*<td[^>]*>((?!(<tr|</td)).)*</td>\\s*){2}\\s*</tr>(\\s*<tr[^>]*>\\s*<td[^>]*>((?!(<tr|</td)).)*</td>\\s*</tr>)*");
        Matcher matcher = pattern.matcher(s);
        while (matcher.find()) {
            MatchResult m = matcher.toMatchResult();
            System.out.println("Match: " + m.group(0));
        }
    }

    public static void main(String[] args) {
        String s = "<tr>\n    <td>XYZ</td>\n    <td><tag1>abc\ndef</tag2></td>\n</tr>\n<tr>\n    <td>XYZ</td>\n</tr>\n<tr>\n    <td>XYZ</td>\n</tr>";
        Test.doMatch(s);
        s = "<tr><td>1></td><td>2</td></tr><tr><td>3></td><td>4</td></tr><tr><td>5></td><td>6</td></tr><tr><td>7</td></tr>";
        Test.doMatch(s);
    }
}

打印:

Match: <tr>
    <td>XYZ</td>
    <td><tag1>abc
def</tag2></td>
</tr>
<tr>
    <td>XYZ</td>
</tr>
<tr>
    <td>XYZ</td>
</tr>
Match: <tr><td>1></td><td>2</td></tr>
Match: <tr><td>3></td><td>4</td></tr>
Match: <tr><td>5></td><td>6</td></tr><tr><td>7</td></tr>