正则表达式-提取外部范围匹配值<table> <table> </table> </table>

时间:2019-10-13 20:56:18

标签: c# regex

string input = "<table>
    <tr>
        <td>Text A</td>
    </tr>
    <tr>
        <td>
            <table>  <!-- Notice this is an inner scope table -->
                <tr>
                    <td>Text B</td>
                </tr>
            </table>
        </td>
    </tr>
</table>

<table>
    <tr>
        <td>
            <table> <!-- Notice this is an inner scope table -->
                <tr>
                    <td>Text C</td>
                </tr>
            </table>
        </td>
    </tr>
</table>

<table>
    <tr>
        <td>Text D</td>
    </tr>
</table>"

我有一系列上述字符串格式的表。

我要提取所有<tr>的第一级中的内容,其中预期的提取内容为:

Text A

<table>
    <tr>
        <td>Text B</td>
    </tr>
</table>

<table>
    <tr>
        <td>Text C</td>
    </tr>
</table>

Text D

我有以下正则表达式描述了我要做什么

var regexTableRow = new Regex("<tr><td>(.*?)</td></tr>");

        var regexMatches = regexTableRow.Matches(htmlInput);

        var tableRows = new List<string>();

        foreach (Match match in regexMatches)
        {
            // Get a row of <tr></tr> out
            var value = match.Value;

            tableRows.Add(value);
        }

正则表达式失败的地方是它从内部表而不是外部表中提取<tr>。在提取过程中,如何使Regex只关注外部表?

谢谢。

[编辑]-谢谢,我将改用HtmlAgilityPack。此代码也面临类似的问题:

var htmlDocument = new HtmlDocument();
            htmlDocument.LoadHtml(htmlInput);

            var output = htmlDocument.DocumentNode
                .SelectNodes("table/tr");

正在拾取内部表而不是外部表的地方。

1 个答案:

答案 0 :(得分:0)

使用正则表达式来做到这一点是很不容易的,但是如果需要,您可以定义一些边界,例如:

(?<=<table>)\s*<tr>\s*<td>([a-z0-9 ]*)<\/td>\s*<\/tr>

否则,它将变得非常复杂。

测试

using System;
using System.Text.RegularExpressions;

public class Example
{
    public static void Main()
    {
        string pattern = @"(?<=<table>)\s*<tr>\s*<td>([a-z0-9 ]*)<\/td>\s*<\/tr>";
        string input = @"<table>
    <tr>
        <td>Text A</td>
    </tr>
    <tr>
        <td>
            <table>  <!-- Notice this is an inner scope table -->
                <tr>
                    <td>Text B</td>
                </tr>
            </table>
        </td>
    </tr>
</table>

<table>
    <tr>
        <td>
            <table> <!-- Notice this is an inner scope table -->
                <tr>
                    <td>Text C</td>
                </tr>
            </table>
        </td>
    </tr>
</table>

<table>
    <tr>
        <td>Text D</td>
    </tr>
</table>";
        RegexOptions options = RegexOptions.Singleline | RegexOptions.IgnoreCase;

        foreach (Match m in Regex.Matches(input, pattern, options))
        {
            Console.WriteLine("'{0}' found at index {1}.", m.Value, m.Index);
        }
    }
}

如果您希望简化/修改/探索表达式,请在regex101.com的右上角进行说明。如果愿意,您还可以在this link中查看它如何与某些示例输入匹配。