将平面HTML标题结构转换为对象图



我需要能够获取WordML文档,并通过其标题将其转换为对象图,该标题将通过web应用程序转换为可导航结构。这可以类似于";导航";窗格。

以下是我需要将Word文档放入的对象结构的一个简单示例:

public class Folder
{
    public string Name { get; set; }
    public string Description { get; set; }
    public Folder ParentFolder { get; set; }
    public ICollection<Folder> Subfolders { get; set; }
    public ICollection<Page> Pages { get; set; }
}
public class Page
{
    public string Title { get; set; }
    public string Content { get; set; }
    public Folder ContainingFolder { get; set; }
}

希望这是不言自明的。它基本上就像一个基本的文件系统。

Word文档可以有多个部分,其中包含任意数量的嵌套标题。如果我们把标题结构看作一棵树,我需要每一片叶子(一个没有副标题的标题部分)都是一个页面,每一个分支都是一个子文件夹。例如:


标题1(a)

部分内容(1)

标题2(b)

标题3(c)

部分内容(2)

标题2(d)

标题3(e)

部分内容(3)

标题3(f)

部分内容(4)

标题4(g)

部分内容(5)


在本例中,(a)将成为新文件夹的名称,(1)为描述,并具有子文件夹(b)和(d),每个子文件夹都将具有空描述。由于(c)没有副标题,因此它将成为标题为(c)、内容为(2)、包含文件夹为(b)的页面。与(e)和(3)相同。(f) 应成为ParentFolder(d)下的新文件夹,说明为(4),以及(g)的新页面,标题为(g),内容为(5)。

我希望我还没有失去你。

到目前为止,我已经尝试过用OpenXMLSDK打开一个文档,但由于处理结果XML有点麻烦,我决定使用库将文档转换为HTML。这提供了一个漂亮、干净的文档,我可以使用LINQ to XML遍历它。

现在我有了一个带有p、h1、h2等标记的平面HTML文档,但很明显,它们不是嵌套的;他们都是兄弟姐妹。如何遍历此文档并将每个标题部分转换为我上面解释的对象图?

需要注意的是:文档可能不总是以H1开头,子标题也可能不总是下一个直接的子标题(例如,H2后面跟着H4)。如果最高级的标题在文档的中间,我们可以忽略它之前的任何内容。

好吧,我想明白了。我还没有测试所有的病例,就像我在问题结尾的警告中提到的那样,但目前,它会起作用。如果有人偶然发现并感兴趣,下面是我所做的。

首先,我最终将Word文档转换为HTML,然后使用LINQ到XML对其进行解析。该方法首先通过传入HTML中的第一个带标题标记的元素("H1"、"H2"等)和一个Folder对象来调用,该对象将包含我在问题中描述的Word到Folder/Page结构的输出。

private Folder ConvertHtmlHeadersToFolderStructure(XElement header, Folder containingFolder)
    {
        // Extract the usable data from the element
        // header.Value
        string title;
        // header.NextNode.ToString() for everything between this and the next header element 
        StringBuilder contentSb; 
        ExtractInfo(header, out title, out contentSb);
        // Determine if this header element is going to be a page or a folder
        // It's a page if the current header element number is greater than or equal to
        // the next header element number, e.g. h3 >= h2; h3 is a page
        XElement nextHeader;
        if (IsElementALeaf(header, out nextHeader))
        {
            containingFolder.Pages.Add(new Page
            {
                Content = contentSb.ToString(),
                Title = title,
                Folder = containingFolder
            });
            if (nextHeader != null)
            {
                int thisHeaderLevel = GetHeaderLevel(header);
                int nextHeaderLevel = GetHeaderLevel(nextHeader);
                Folder upLevelFolder = containingFolder;
                for (int i = 0; i < thisHeaderLevel - nextHeaderLevel; i++)
                {
                    upLevelFolder = upLevelFolder.ParentFolder;
                }
                ConvertHtmlHeadersToFolderStructure(nextHeader, upLevelFolder);
            }
            return containingFolder;
        }
        else
        {
            Folder subFolder = new Folder
            {
                Description = contentSb.ToString(),
                Name = title,
                ParentFolder = containingFolder
            };
            // nextHeader shouldn't be null if we got here
            subFolder = ConvertHtmlHeadersToFolderStructure(nextHeader, subFolder);
            containingFolder.Subfolders.Add(subFolder);
            return containingFolder;
        }
    }

相关内容

  • 没有找到相关文章