使用 MariGold.OpenXHTML 和 AngleSharp 将 HTML 转换为 Open XML Word 文档
逐步指南,介绍如何将 AngleSharp HTML 解析器集成到 MariGold.OpenXHTML 中
引言
MariGold.OpenXHTML
是一个开源的 GitHub库,用于将 HTML 文档转换为 Open XML Word 文档。它使用内部 HTML 解析器来读取 HTML 元素。此 HTML 解析器可以完全替换为您喜欢的 HTML 解析器。在这里,我将演示如何使用流行的 AngleSharp HTML 解析器来完成此操作。
Using the Code
MariGold.OpenXHTML
依赖于两个接口来读取 HTML。我们只需要为这两个接口创建实现。这些接口是:
MariGold.HtmlParser.IHtmlNode
- 这只是 HTML 元素的容器。我们的自定义 HTML 解析器使用它来创建 HTML 节点元素的层次结构,以便在 MariGold.OpenXHTML
中进行处理。
MariGold.OpenXHTML.IParser
- 用于实现自定义 HTML 解析器。我们将 AngleSharp 集成到其中,以处理 HTML 字符串
。
打开 Visual Studio 并创建一个控制台应用程序项目。在根目录下创建一个名为 source.html 的文件,并填入您想要转换的 HTML 内容。选择此 HTML 文件的属性,并将 **复制到输出目录** 属性设置为 **始终复制**,以便我们的演示可以处理该文件在 bin 文件夹中可用。
下一步是安装 MariGold.OpenXHTML
nuget 包。从 工具 -> NuGet 包管理器 -> 包管理器控制台执行命令 Install-Package MariGold.OpenXHTML
。这将把以下包安装到您的项目中。MariGold.HtmlParser
是默认的 HTML 解析器。在这里,我们将只使用这个库中的一个接口来进行我们的自定义实现。
DocumentFormat.OpenXml
MariGold.HtmlParser
MariGold.OpenXHTML
实现 MariGold.HtmlParser.IHtmlNode
创建一个名为 AngleNode
的类,并让它继承自 MariGold.HtmlParser.IHtmlNode
。在此类中创建一个构造函数,接受一个 AngleSharp.Dom.INode
类型的对象,并将其存储在一个 private
变量中。我们将使用此节点来提取 IHtmlNode
所需的属性。
private readonly INode node;
internal AngleNode(INode node)
{
this.node = node;
}
这些属性用于 MariGold.OpenXHTML
创建等效的 Open XML 元素属性。并非 IHtmlNode
的所有属性都在 MariGold.OpenXHTML
中使用。下面列出了必需的属性。您可以在随附的示例项目中找到这些属性的实现细节。
Attributes
- 所有 HTML 属性的字典Children
- 包含文本元素的子元素的IEnumerable
集合HasChildren
- 一个布尔属性,用于检查元素是否具有子元素InnerHtml
- 元素的内部 HTML,以string
格式表示。主要用于获取文本元素的内容IsText
- 用于识别节点是文本元素还是非文本元素Next
- 下一个同级元素。如果没有这样的元素,则为null
Parent
- 父元素。如果是根元素,则为null
Previous
- 前一个同级元素。如果没有这样的元素,则为null
Styles
- 所有样式属性的字典Tag
- HTML 元素的标签名
实现 MariGold.OpenXHTML.IParser
此接口位于 MariGold.OpenXHTML 命名空间
。它负责解析 HTML 文档。它包含两个属性和两个方法。为了实现这些属性和方法,请创建一个名为 AngleParser
的类,并让它继承自 IParser
。如下所示实现这两个属性。这些属性不需要包含任何逻辑。它们只是 HTML 文档中任何相对或无协议 URL 引用的基本 URL 和 URI Schema 的容器。
public string BaseURL { get; set; }
public string UriSchema { get; set; }
接下来,我们将实现 CalculateRelativeChildFontSize
方法。有时,MariGold.OpenXHTML
需要计算某些 HTML 元素的相对字体大小。有关更多信息,请参阅 GitHub 中的 HTML 解析部分。如果您不想重新处理此问题,可以使用默认实现。就像下面的方法一样。
public decimal CalculateRelativeChildFontSize(string parentFontSize, string childFontSize)
{
return MariGold.HtmlParser.CSSUtility.CalculateRelativeChildFontSize
(parentFontSize, childFontSize);
}
接下来,在 AngleParser
中创建一个构造函数,接受一个 HTML 字符串
。此构造函数会将 HTML 字符串
加载到一个 private
变量中,以便稍后处理。
private readonly string html;
public AngleParser(string html)
{
this.html = html;
}
IParser
接口中的最后一个方法是 FindBodyOrFirstElement
方法。这是我们自定义解析器实现的核心方法。在实现此方法之前,请使用 NuGet 包管理器安装 AngleSharp
。然后,在 AngleParser
中编写一个 private
方法来读取 HTML 字符串
,并使用 AngleSharp
获取 HTML body
元素。
private IHtmlElement ParseBody()
{
var parser = new AngleSharp.Parser.Html.HtmlParser(Configuration.Default.WithCss());
var doc = parser.Parse(html);
return doc.Body;
}
FindBodyOrFirstElement
方法应返回 HTML Body 元素的 IHtmlNode
类型实现,如果 HTML 字符串
中缺少 body 元素,则返回根元素。
public MariGold.HtmlParser.IHtmlNode FindBodyOrFirstElement()
{
return new AngleNode(ParseBody());
}
现在,自定义 HTML 解析器实现已准备好集成到 MariGold.OpenXHTML
中。在控制台应用程序的主方法中编写以下代码。AngleParser
从 source.html 读取 HTML 字符串
,并在 WordDocument
类中进行解析。
WordDocument doc = new WordDocument("sample.docx");
using (StreamReader sr = new StreamReader("source.html"))
{
doc.Process(new AngleParser(sr.ReadToEnd()));
}
doc.Save();