从table-element中分解html元素

时间:2018-02-22 16:41:27

标签: c# html xpath html-agility-pack

我在查找以下代码中打破H4标记的正确方法时遇到了问题。我不仅需要让它保留在代码中,而且我还需要删除它当前所在的表。

那么,如何删除整个表并将h4-tag保留在原来的位置?

<table align="center" border="0" cellpadding="0" cellspacing="0">
<tr><td height="30" align="center" colspan="5"><h4>IMPORTANT HEADLINE ABOUT THIS PARTICULAR PAGE</h4></td></tr>
  <tr> 
    <td><a href="index.html" target="_top" onclick="MM_nbGroup('down','group1','contents','',1)" onmouseover="MM_nbGroup('over','contents','../figs/contents1.gif','',1)" onmouseout="MM_nbGroup('out')"><img name="contents" src="../figs/contents.gif" border="0" alt="" onload=""></a></td>
    <td><a href="../page.html" target="_top" onclick="MM_nbGroup('down','group1','authorindex','',1)" onmouseover="MM_nbGroup('over','authorindex','../figs/iauthori1.gif','',1)" onmouseout="MM_nbGroup('out')"><img src="../figs/iauthori.gif" alt="" name="authorindex" width="120" height="20" border="0" onload=""></a></td>
    <td><a href="../page.html" target="_top" onclick="MM_nbGroup('down','group1','subjindex','',1)" onmouseover="MM_nbGroup('over','subjindex','../figs/isubji1.gif','',1)" onmouseout="MM_nbGroup('out')"><img src="../figs/isubji.gif" alt="" name="subjindex" width="120" height="20" border="0" onload=""></a></td>
    <td><a href="../search.html" target="_top" onclick="MM_nbGroup('down','group1','search','',1)" onmouseover="MM_nbGroup('over','search','../figs/isearch1.gif','',1)" onmouseout="MM_nbGroup('out')"><img src="../figs/isearch.gif" alt="" name="search" width="120" height="20" border="0" onload=""></a></td>
    <td><a href="../page.html" target="_top" onclick="MM_nbGroup('down','group1','home','',1)" onmouseover="MM_nbGroup('over','home','../figs/ihome1.gif','',1)" onmouseout="MM_nbGroup('out')"><img name="home" src="../figs/ihome.gif" border="0" alt="" onload=""></a></td>
  </tr>
</table>

此外,我有大约2500个类似结构的html文档,但是在不同版本的HTML中,因此使用div,表或其他元素从版本到版本。所以我需要一种方法来正确地改变这种方法。

我已准备好文档加载,它会将所有文件加载到列表中,因此我将为此文件名列表提供一个方法来打开和解析。但我无法弄清楚如何使用XPath。

2 个答案:

答案 0 :(得分:1)

解决问题的一种方法是找到所有<h4>个节点,沿着它的父链走,直到找到 stop 标记/节点,并替换使用<h4>停止标记/节点:

给出了一些驻留在 HTML文件中的示例HTML

var html =
@"<!doctype html system 'html.dtd'>
<html><head></head>
<body>
<table align='center' border='0' cellpadding='0' cellspacing='0'>
<tr><td height='30' align='center' colspan='5'><h4>IMPORTANT HEADLINE ABOUT THIS PARTICULAR PAGE</h4></td></tr>
  <tr> 
    <td><a href='index.html'><img name='contents' src='../figs/contents.gif' border='0' alt='' onload=''></a></td>
    <td><a href='../page.html'><img src='../figs/iauthori.gif' alt='' name='authorindex' width='120' height='20' border='0' onload=''></a></td>
    <td><a href='../page.html'><img src='../figs/isubji.gif' alt='' name='subjindex' width='120' height='20' border='0' onload=''></a></td>
    <td><a href='../search.html'><img src='../figs/isearch.gif' alt='' name='search' width='120' height='20' border='0' onload=''></a></td>
    <td><a href='../page.html'><img name='home' src='../figs/ihome.gif' border='0' alt='' onload=''></a></td>
  </tr>
</table>

<div>
<h4>H4 nested in DIV</h4>
<p>Paragraph <strong>bold</strong> <a href=''>Hyperlink</a></p>
</div>

<p><h4>H4 nested in P</h4></p>

</body>
</html>";

用这种方法解析它:

public string ParseHtmlToString(string inputFilePath)
{
    var document = new HtmlDocument();
    document.Load(inputFilePath);
    var wantedNodes = document.DocumentNode.SelectNodes("//h4");
    // stop at these tags while walking backwards up the chain
    var stopTags = new string[] { "table", "div", "p" };
    HtmlNode parentNode;

    foreach (var node in wantedNodes)
    {
        HtmlNode testNode = node;
        while ((parentNode = testNode.ParentNode) != null)
        {
            if (stopTags.Contains(parentNode.Name))
            {
                parentNode.ParentNode.ReplaceChild(node, parentNode);
            }
            testNode = parentNode;
        }
    }

    return document.DocumentNode.WriteTo();
}

然后您可以将解析后的HTML分配给这样的变量:

var parsedHtml = ParseHtmlToString(INPUT_FILE);

返回以下值:

<!doctype html system 'html.dtd'>
<html><head></head>
<body>
<h4>IMPORTANT HEADLINE ABOUT THIS PARTICULAR PAGE</h4>

<h4>H4 nested in DIV</h4>

<h4>H4 nested in P</h4>

</body>
</html>

答案 1 :(得分:0)

这是另一种解决方案,它适用于Kuujinbo解决方案失败的所有文档,我将它们作为try / final / catch方法并排运行。所有2500个html-docs都能很好地工作。

try {ParseHtmlToString(file)}
final {myAlternateSolution(file)}
catch (Exception Ex){Console.WriteLine(file +":"+ Ex.Message);}

基本上它是以

运行的
all()

它起作用的原因是该表大部分时间都是正文之后的第一个节点,它也是文档中的第一个表。由于某些文档的HTML格式错误,无法使用HTMLTidy等修复,因此必须进行一些手动编辑。