【问题标题】:Break out an html-element from within a table-element从表格元素中拆分出一个 html 元素
【发布时间】:2018-08-02 14:52:45
【问题描述】:

我在寻找从以下代码中拆分 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。

【问题讨论】:

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


    【解决方案1】:

    解决问题的一种方法是找到所有&lt;h4&gt; 节点,沿着它的父链向上走,直到找到一个 stop 标记/节点,然后替换 stop使用您的&lt;h4&gt; 标记/节点:

    给定一些位于 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();
    }
    

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

    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>
    

    【讨论】:

    • 感谢代码!但是,我想将其余代码保留在文档中。这意味着我只想删除包含文档重要标题的 h4 周围的表格。我还没有测试你的东西..但我相信它会按照你说的那样做。但据我了解,我可以将表格作为我的停止标签,并且只删除其中的 h4 吗?问题是我在这些文档中还有其他“表格”,其中包含研究数据,需要保持完整。
    • 您介意看看我与此相关的其他问题吗? stackoverflow.com/questions/48891744/…
    • @ChristerJohansson - 是的,代码将删除具有&lt;h4&gt;&lt;table&gt;。其他所有&lt;table&gt; 都保持不变。
    • 抱歉回复晚了。我无法理解这一点。在第一次运行时(在 foreach 循环中),它打印出 H4 标记,第二次运行也打印出,但在第 3 次和第 4 次运行时,它打印出未经编辑的原始 html,有点恢复它。您是否介意澄清我将如何以一种基本方法实现您的解决方案,将已编辑的数据保存到变量中?循环完成后,我会将其保存到 foreach 循环中的原始文件中。
    • 不确定为什么代码不适合您,除非您的 HTML 文件包含与示例不同的标记。答案已经过测试并且有效。无论如何,更新答案以反映您上面的评论:包括一个简单的方法,该方法接受 HTML 文件的 完整文件路径,对其进行解析,然后返回 string,以便您可以将编辑后的 ​​HTML 分配给一个变量。
    【解决方案2】:

    这是一个替代解决方案,它适用于 Kuujinbo 解决方案失败的所有文档,我将它们作为 try/final/catch 方法并排运行。它在所有 2500 个 html 文档中运行良好。

    var doc = new HtmlDocument();
    doc.Load(file);
    var htmlBody = doc.DocumentNode.SelectSingleNode("//body");
    var headerTables = doc.DocumentNode.SelectSingleNode("//body/table[1]");
    var headerNode = doc.DocumentNode.SelectSingleNode("//h4[contains(text(),'Information Research, Vol')]");
    htmlBody.ReplaceChild(headerNode, headerTables);
    headerTables.Remove();
    doc.Save(file);
    

    基本上是这样运行的

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

    之所以有效,是因为该表大多数时候是正文之后的第一个节点,并且它也是文档中的第一个表。由于某些文档的 HTML 格式错误,并且无法使用 HTMLTidy 等修复,因此必须进行一些手动编辑。

    【讨论】:

      猜你喜欢
      • 2017-04-25
      • 2021-04-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-10-06
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多