【问题标题】:Use HtmlAgilityPack to divy up a document使用 HtmlAgilityPack 划分文档
【发布时间】:2010-08-18 22:41:13
【问题描述】:

我想知道这是否可能。

我有这样的html:

<p>
  <font face="Georgia">
    <b>History</b><br>&nbsp; <br>Two of the polysaccharides used in the manufacture of...</font>
    <a title="PubMed" href="http://www.www.gov/pubmed/" target="_blank">
    <font face="Georgia">) and this web site for new development by...well as Self Affirmed Medical Food GRAS status.&nbsp; 
    </font>
</p>

<p>
  <font face="Georgia">[READMORE]</font>
</p>

<p><font face="Georgia"><br><strong>Proprietary Composition</strong><br>
   <br>The method in which soluble fibres are made into... REST OF ARTICLE...
</p>

是的,它是丑陋的 html,它来自所见即所得,所以我几乎无法控制它。

我想做的是在文档中搜索 [READMORE],删除所有父标签(在本例中为 &lt;font&gt;&lt;p&gt; 标签)并将它们替换为阅读更多链接,同时将文档的 REST 包装在一个巨大的`...文章的其余部分...

我很确定 HtmlAgilityPack 将帮助我实现这一目标,但我只是想弄清楚从哪里开始。

到目前为止,我很确定我必须使用 htmlDoc.DocumentNode.SelectSingleNode(//p[text()="[READMORE]"]) 或其他东西。我对 XPATH 不太熟悉。

对于我的文档,readmore 可能会也可能不会在嵌套的font 标记中。

此外,在某些情况下,它可能根本不在标签中,而是在文档根目录中。在这种情况下,我可以进行常规搜索和替换,它应该很简单。

我的理想情况是这样的(伪代码)

var node = SelectNodeContaining("[READMORE]").

node.Replace( "link here" );

node.RestOfDocument().Wrap("<div class='wrapper'");

我知道,我在做梦……但我希望这是有道理的。

【问题讨论】:

  • 您是否考虑过在发送所见即所得的输出之前执行此客户端?
  • 使用 XSLT 最容易做到这一点。添加“xslt”标签,您几乎会立即收到许多好的答案。
  • @Dimitre。谢谢小费。完成。
  • _-Ib:请参阅我对 XSLT 解决方案的回答,该解决方案可以完全根据您的要求转换您的文档。

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


【解决方案1】:

这是一个 XSLT 解决方案

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output method="xml" omit-xml-declaration="yes" indent="yes"/>
 <xsl:strip-space elements="*"/>

 <xsl:template match="node()|@*">
  <xsl:copy>
   <xsl:apply-templates select="node()|@*"/>
  </xsl:copy>
 </xsl:template>

 <xsl:template match="p[descendant::text()[. = '[READMORE]']]">
  <a href="#ReadmoreWrapper">READMORE</a>
  <div class="wrapper" id="#ReadmoreWrapper">
   <xsl:apply-templates select="following-sibling::node()" mode="copy"/>
  </div>
 </xsl:template>

 <xsl:template match=
  "node()[ancestor::p[descendant::text()[. = '[READMORE]']]
         or
          preceding::p[descendant::text()[. = '[READMORE]']]
          ]
  "/>

  <xsl:template match="node()|@*" mode="copy">
      <xsl:copy>
       <xsl:apply-templates select="node()|@*" mode="copy"/>
      </xsl:copy>
  </xsl:template>
</xsl:stylesheet>

当此转换应用于以下 XML 文档时

<html>
<p>
  <font face="Georgia">
    <b>History</b><br/>&#xA0; <br/>Two of the polysaccharides used in the manufacture of...</font>
    <a title="PubMed" href="http://www.www.gov/pubmed/" target="_blank"/>
    <font face="Georgia">) and this web site for new development by...well as Self Affirmed Medical Food GRAS status.&#xA0;
    </font>
</p>

<p>
  <font face="Georgia">[READMORE]</font>
</p>

<p><font face="Georgia"><br/><strong>Proprietary Composition</strong><br/>
   <br/>The method in which soluble fibres are made into... REST OF ARTICLE...
   </font>
</p>

</html>

产生想要的结果

<html>
    <p>
        <font face="Georgia"><b>History</b><br/>  <br/>Two of the polysaccharides used in the manufacture of...</font>
        <a title="PubMed" href="http://www.www.gov/pubmed/" target="_blank"/>
        <font face="Georgia">) and this web site for new development by...well as Self Affirmed Medical Food GRAS status. 
    </font>
    </p>
    <a href="#ReadmoreWrapper">READMORE</a>
    <div class="wrapper" id="#ReadmoreWrapper">
        <p>
            <font face="Georgia"><br/><strong>Proprietary Composition</strong><br/><br/>The method in which soluble fibres are made into... REST OF ARTICLE...
   </font>
        </p>
    </div>
</html>

【讨论】:

  • 它似乎可以工作,但我遇到了解析错误。解析为 XML Doc 时,它不喜欢文本中的&amp;nbsp;。可以在HtmlAgilityPack.HtmlDocument 上完成相同的 XSLT 转换吗?"
  • 我认为 HtmlAgilityPack 会生成 XML 文档。如果不是这样,您可以通过编程将其 HTML DOM 转换为 XML 树 (DOM)。当我编写转换时,我用&lt;br /&gt; 替换了所有@nbsp; 和所有未关闭的标签,如&lt;br&gt;,并添加了一些结尾&lt;/font&gt; 标签。很可能这些人有一个 XML 序列化器。
  • 对于仍在寻找解决方案的任何人,我已经按照上述方法完成了此操作,并且可以正常工作。将文档加载到 HtmlAgilityPack.HtmlDocument 中,使用选项强制输出符合 XML,保存文档,然后将其加载到标准 .NET XmlDocument 对象中。从那里你可以运行你的 XSLT 等。
【解决方案2】:

如果我是对的,你可以尝试一件事......就像我们在发送自定义 html 邮件时所做的一样

  1. 为您的 html 页面创建一个包含静态内容的模板。
  2. 为动态内容附加标识符,如您所说的 [ReadMore] 或 {ReadmOre} 或类似内容。
  3. 现在逐行读取模板 html 文件并将标识符替换为所需的文本。
  4. 现在将整个字符串保存到一个新的 html 文件或做任何你想做的事情。

【讨论】:

  • 计划就是这样。但是,如果我用链接替换 ​​[Readmore] 并将文章的其余部分从那时起封装在一个 div 标签中,我将有未闭合的标签。我需要删除 [readmore] 的父母(如果存在),然后执行此操作。我一直坚持以一致的方式删除它们。
猜你喜欢
  • 1970-01-01
  • 2017-08-16
  • 1970-01-01
  • 2012-11-04
  • 1970-01-01
  • 2011-08-23
  • 1970-01-01
  • 1970-01-01
  • 2023-04-02
相关资源
最近更新 更多