项目需要将html table 表格转换为Datatable对象,表格信息如下:
<table>
<tbody>
<tr>
<th>标题</th>
<th>内容</th>
</tr>
<tr>
<td>Animate(Image, EventHandler)</td>
<td>将多帧图像显示为动画。</td>
</tr>
<tr>
<td>CanAnimate(Image)</td>
<td>返回一个布尔值,该值指示指定图像是否包含基于时间的帧。</td>
</tr>
<tr>
<td>Equals(Object)</td>
<td>确定指定对象是否等于当前对象。(继承自 Object)</td>
</tr>
<tr>
<td>GetHashCode()</td>
<td>作为默认哈希函数。(继承自 Object)</td>
</tr>
<tr>
<td>GetType()</td>
<td>获取当前实例的 Type。(继承自 Object)</td>
</tr>
<tr>
<td>MemberwiseClone()</td>
<td>创建当前 Object 的浅表副本。(继承自 Object)</td>
</tr>
<tr>
<td>StopAnimate(Image, EventHandler)</td>
<td>终止正在运行的动画。</td>
</tr>
<tr>
<td>ToString()</td>
<td>返回表示当前对象的字符串。(继承自 Object)</td>
</tr>
<tr>
<td>UpdateFrames()</td>
<td>使该帧在当前正被动画处理的所有图像中前移。 新帧在下一次呈现图像时绘制。</td>
</tr>
<tr>
<td>UpdateFrames(Image)</td>
<td>使帧在指定的图像中前移。 新帧在下一次呈现图像时绘制。 此方法只适用于包含基于时间的帧的图像。</td>
</tr>
</tbody>
</table>
<table border="1">
<tr>
<th>1</th>
<th>2</th>
<th>3</th>
<th>4</th>
<th>5</th>
<th>6</th>
</tr>
<tr>
<td rowspan="3">1</td>
<td>2</td>
<td>3</td>
<td>4</td>
<td>5</td>
<td>6</td>
</tr>
<tr>
<td>7</td>
<td rowspan="2" colspan="3">8</td>
<td>9</td>
</tr>
<tr>
<td>10</td>
<td>11</td>
</tr>
</table>
一个是正常的table,另外一个带有 rowspan 和 colspan ,这种情况就比较复杂.查询相关资料,发现使用HtmlAgility 类库,可以非常方便的进行HTML解析.
核心代码如下:
DataTable dt = new DataTable();
//获取所有的td行信息
var rowlist = docchild.DocumentNode.SelectNodes("//tr[td]");
if (rowlist == null) { continue; }
//取第一行的数据,来确定总的列数
var colcount = 0;
foreach (var td in rowlist[0].ChildNodes.Where(m => m.OriginalName.ToLower() == "td"))
{
var attr = td.Attributes["colspan"];
var colspan = (attr != null) ? int.Parse(attr.Value) : 1;
colcount = colcount + colspan;
}
var headers = docchild.DocumentNode.SelectNodes("//tr/th");
//如果最大的行数和标题列数相同,则取标题,其它则重新设置
bool setcol = false;
if (headers != null)
{
if (headers.Count == colcount) { foreach (HtmlNode header in headers) { dt.Columns.Add(header.InnerText); } setcol = true; }
}
if (!setcol)
{
for (var i = 1; i <= colcount; i++) { dt.Columns.Add("列" + i.ToString()); }
}
var arr = new string[rowlist.Count][];
for (var r = 0; r < rowlist.Count; r++)
{
arr[r] = new string[colcount];
}
for (var row = 0; row < rowlist.Count; row++)
{
var cols = rowlist[row].ChildNodes.Where(m => m.OriginalName.ToLower() == "td").ToList();
for (var column = 0; column < cols.Count; column++)
{
var cAttr = cols[column].Attributes["colspan"];
var colspan = (cAttr != null) ? int.Parse(cAttr.Value) : 1;
var rAttr = cols[column].Attributes["rowspan"];
var rowspan = (rAttr != null) ? int.Parse(rAttr.Value) : 1;
var text = string.IsNullOrEmpty(cols[column].InnerText) ? "" : cols[column].InnerText;
var startColumn = 0;
for (var i = 0; i < rowspan; i++)
{
for (var j = 0; j < colspan; j++)
{
var d = startColumn == 0 ? column : startColumn;
if (string.IsNullOrEmpty(arr[row + i][d + j]))
arr[row + i][d + j] = text;
else
{
var t = column + j + 1;
startColumn = t;
while (true)
{
if (string.IsNullOrEmpty(arr[row][t]))
{
arr[row][t] = text;
break;
}
t++;
}
}
}
}
}
}
for (var i = 0; i < arr.Length; i++)
{
var row = dt.NewRow();
for (var k = 0; k < arr[i].Length; k++)
{
var columnTxt = arr[i][k] == "" ? "" : arr[i][k];
row[k] = columnTxt;
}
dt.Rows.Add(row);
}
listtd.Add(dt);
转化后的效果如下:
下面是随便复制一个含有多个HTML table的页面内容,然后进行转换: