重复组以形成对象

时间:2016-02-05 08:58:42

标签: regex html-agility-pack

我有一个像这样的html表:

<table style="width:100%">
  <tr>
    <td class="country">Germany</td>
  </tr>
  <tr>
    <td class="city">Berlin</td>
  </tr>
  <tr>
    <td class="city">Cologne</td>
  </tr>
  <tr>
    <td class="city">Munich</td>
  </tr>
   <tr>
    <td class="country">France</td>
  </tr>
  <tr>
    <td class="city">Paris</td>
  </tr>
      <tr>
    <td class="country">USA</td>
  </tr>
  <tr>
    <td class="city">New York</td>
  </tr>
  <tr>
    <td class="city">Las Vegas</td>
  </tr>
</table>

从这张表中,我想生成像Country和City这样的对象。国家将有一个城市名单。

现在问题: 创建一个正则表达式以获得所有国家和所有城市很容易,但我想知道我是否可以让城市的团体重复,直到下一个国家开始?我需要这样做,因为我无法以编程方式弄清楚哪个城市属于哪个国家,如果我将它们分开进行正则表达式匹配。

它应该像(快速和肮脏的解决方案):

country">([\w]*)<{.*\n.*\n.*\n.*"city">([\w]*)}

应该重复花括号直到下一个国家/地区项目出现。

如果您对如何从c#中的html表中获取对象有完全不同的想法,请告诉我!

提前致谢!

1 个答案:

答案 0 :(得分:1)

同意对于任何非平凡的HTML,应使用HtmlAgilityPack HTML解析器。话虽如此,如果您的HTML与上面的代码段一样简单,即使字符串中有多个换行符,也可以这样做:

string HTML = @"
<table style='width:100%'>
    <tr><td class='country'>Germany</td></tr>
    <tr><td class='city'>Berlin</td></tr>
    <tr><td class='city'>Cologne</td></tr>
    <tr><td class='city'>Munich</td></tr>
    <tr><td class='country'>France</td></tr>
    <tr><td class='city'>Paris</td></tr>
    <tr><td class='country'>USA</td></tr>
    <tr><td class='city'>New York</td></tr>
    <tr><td class='city'>Las Vegas</td></tr>
</table>";

var regex = new Regex(
    @"
        class=[^>]*?
        (?<class>[-\w\d_]+)
        [^>]*>
        (?<text>[^<]+)
        <
    ",
    RegexOptions.Compiled | RegexOptions.IgnoreCase 
    | RegexOptions.IgnorePatternWhitespace
);

var country = string.Empty;
var Countries = new Dictionary<string, List<string>>();
foreach (Match match in regex.Matches(HTML))
{
    string countryCity = match.Groups["class"].Value.Trim();
    string text = match.Groups["text"].Value.Trim();
    if (countryCity.Equals("country", StringComparison.OrdinalIgnoreCase))
    {
        country = text;
        Countries.Add(text, new List<string>());
    }
    else
    {
        Countries[country].Add(text);
    }
}