6

我想做的是在 aCommentRangeStart和相应的CommentRangeEnd.

我尝试了两种方法来实现这一点,但是问题是CommentRangeEnd不需要与开始处于同一水平。它可以嵌套在子元素中,请参见下面非常简单的结构(注意这不是正确的打开 xml,它只是为了展示一般想法)。

<w:commentstart/>
<w:paragraph>
  <w:run />
  <w:commentend />
</w:paragraph>

我尝试过的两个项目如下:首先:我写了一个可枚举,它返回项目直到结束

public static IEnumerable<OpenXmlElement> SiblingsUntilCommentRangeEnd(CommentRangeStart commentStart)
{
    OpenXmlElement element = commentStart.NextSibling();

    if (IsMatchingCommentEnd(element, commentStart.Id.Value))
    {
        yield break;
    }

    while (true)
    { 
        yield return element;
        element = element.NextSibling();

        // Check that the item 
        if (element == null)
        {
            yield break;
        }

        if (IsMatchingCommentEnd(element, commentStart.Id.Value))
        {
            yield break;
        }
    }
}

public static bool IsMatchingCommentEnd(OpenXmlElement element, string commentId)
{
    CommentRangeEnd commentEnd = element as CommentRangeEnd;
    if (commentEnd != null)
    {
        return commentEnd.Id == commentId;
    }
    return false;
}

第二:然后意识到开始和结束不在同一水平上的问题,我继续四处寻找,我发现Eric Whites 回答了处理书签元素之间的元素,我为我的示例重新安装了它,但仍然是开始和结束的问题end 没有相同的父母(即在同一级别)是一个问题,我不能使用它。

有没有更好的方法来看待这个我正在寻找一种处理元素的方法,因为我需要处理正在评论的文本。

编辑: 澄清我想要实现的目标:我正在使用 word 编辑的文档,并在文档中添加评论.

编辑 2: 我已经提出了我目前正在考虑的工作版本,但我的问题是它可能非常脆弱,与 Word 不同的用户组合。这也适用于 xml,这不是一个真正的问题,但可能希望更改为 OpenXML SDK。目前看起来我需要解析整个文档来获取我需要的项目,而不是使用 1 个特定的评论。 https://github.com/mhbuck/DocumentCommentParser/

遇到的主要问题:CommentRangeStartandCommentRangeEnd可以在 XML 文档中的不同嵌套中。根节点可能是唯一相似的祖先元素。

4

1 回答 1

3

您可以尝试使用Descendants<T>()方法来枚举给定类型的节点的所有后代。因此,您的代码可能看起来与此类似(我已经编写了它,但没有使用yeld使其更具可读性;)):

public static IEnumerable<OpenXmlElement> SiblingsUntilCommentRangeEnd(CommentRangeStart commentStart)
{
    List<OpenXmlElement> commentedNodes = new List<OpenXmlElement>();

    OpenXmlElement element = commentStart;

    while (true)
    {
        element = element.NextSibling();

        // check that the item exists
        if (element == null)
        {
            break;
        }

        //check that the item is matching comment end
        if (IsMatchingCommentEnd(element, commentStart.Id.Value))
        {
            break;
        }

        //check that there is a matching element in the current element's descendants
        var descendantsCommentEnd = element.Descendants<CommentRangeEnd>();
        if (descendantsCommentEnd != null)
        {
            foreach (CommentRangeEnd rangeEndNode in descendantsCommentEnd)
            {
                if (IsMatchingCommentEnd(rangeEndNode, commentStart.Id.Value))
                {
                    //matching range end element found in current element's descendants
                    //an improvement could be made here to manually select descendants before CommentRangeEnd node
                    break;
                }
            }
        }

        commentedNodes.Add(element);
    }

    return commentedNodes;
}

正如其中一条评论所标记的,如果它CommentRangeEnd在当前元素的后代中找到元素,它现在就结束了。

我还没有测试过这段代码,所以如果你有任何问题,请在评论中告诉我。

请注意,如果开始元素在文档的层次结构中比结束元素更深,则此方法将不起作用。在某些情况下,它也不会返回评论中的某些内容。如果您需要它,我稍后可以使用替代解决方案来更新答案以处理这种情况。还请解释为什么您需要找到这些评论,因为也许可以使用另一种方法。

于 2012-08-29T19:40:52.543 回答