检索对OpenXML评论的引用

问题描述 投票:2回答:2

我试图从Word文档中提取出OpenXML中注释所引用的文本。我可以很容易地得到一个注释的文本,但不能得到该注释所引用的文档中的段落文本。

我附上的图片显示了一个注释和相关文本。我在寻找如何获取引用文本的例子时遇到了很多麻烦。我怎样才能得到这段文字?

Image of text I need

openxml openxml-sdk
2个回答
3
投票

解决方法是获取评论的Id,正如你所说你已经知道如何检索,然后搜索文档中具有相同Id的CommentRangeStart元素。当你找到它后,你可以循环使用.NextSibling(),直到找到一个CommentRangeEnd元素。

在CommentRangeStart和CommentRangeEnd之间的元素是引用的部分,显然可以是多个运行,段落,图片,什么的。所以你必须在之后以某种方式处理收集到的元素。

我做了一个测试文档,看起来是这样的。document example

我做了这个代码来测试它。

using (var wordDoc = WordprocessingDocument.Open(@"c:\test\test.docx", true))
{
    MainDocumentPart mainPart = wordDoc.MainDocumentPart;
    var document = mainPart.Document;
    var comments = mainPart.WordprocessingCommentsPart.Comments.ChildElements;
    foreach(Comment comment in comments)
    {
        string commentId = comment.Id;
        string commentText = comment.InnerText;
        OpenXmlElement rangeStart = document.Descendants<CommentRangeStart>().Where(c => c.Id == commentId).FirstOrDefault();
        List<OpenXmlElement> referenced = new List<OpenXmlElement>();
        rangeStart = rangeStart.NextSibling();

        while(!(rangeStart is CommentRangeEnd))
        {
            referenced.Add(rangeStart);
            rangeStart = rangeStart.NextSibling();
        }

        Console.WriteLine("Comment Id " + commentId + " with text \"" + " " + commentText + "\" references =>");

        foreach (var ele in referenced)
        {
            if(!string.IsNullOrWhiteSpace(ele.InnerText))
            {
                Console.WriteLine("      " + ele.InnerText);
            }
        }
    }
    Console.ReadKey();
}

它产生了这样的输出Console output of code

希望能帮到你


0
投票

我不能让你的解决方案工作。不过我找到了一个变通的方法。

 OpenXmlElement rangeStart = document.Descendants<CommentRangeStart>().Where(c => c.Id == commentId).FirstOrDefault();

                bool breakLoop = false;
                rangeStart = rangeStart.Parent;

 while (true) // Looping through items between commentRangeStart and commentRangeEnd.
                {
                    if (rangeStart.NextSibling() == null)
                    {
                        break;
                    }
                    foreach (var ele in rangeStart.ChildElements)
                    {
                        if (!(ele is CommentRangeEnd))
                        {
                            if (!(string.IsNullOrWhiteSpace(ele.InnerText)))
                            {
                                referenced.Add(ele);
                            }
                        }
                        else
                        {
                            breakLoop = true;
                        }
                        if (breakLoop)
                            break;
                    }
                    rangeStart = rangeStart.NextSibling();
                }

因此,我没有在CommenRageStart存在的段落中循环,因为一个评论可能由几个段落组成,我使用父节点来追踪段落之间的来回。最后,当我到达CommentRangeEnd时,我可以打破循环,并根据需要处理数据。

© www.soinside.com 2019 - 2024. All rights reserved.