在CommentRangeStart和CommentRangeEnd之间获取OpenXmlElements

Mik*_*e B 6 c# openxml openxml-sdk

我想要做的是找到a CommentRangeStart和相应的之间的OpenXMLElements CommentRangeEnd.

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

<w:commentstart/>
<w:paragraph>
  <w:run />
  <w:commentend />
</w:paragraph>
Run Code Online (Sandbox Code Playgroud)

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

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;
}
Run Code Online (Sandbox Code Playgroud)

第二:然后意识到开始和结束没有处于同一水平的问题我继续寻找并且我发现Eric Whites回答处理书签元素之间的元素我复古适合我的例子但仍然是开始的问题和结束没有相同的父母(即在同一水平)是一个问题,我不能使用它.

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

编辑: 澄清我想要实现的目标:我正在使用文字编辑的文档和文档中的注释我希望获得在特定注释id的开始和结束范围之间评论的文本.

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

主要问题遭遇:该CommentRangeStartCommentRangeEnd可以在XML文档中的不同嵌套.根节点可能是唯一类似的祖先元素.

Luk*_*z M 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;
}
Run Code Online (Sandbox Code Playgroud)

正如评论之一所标记的,如果CommentRangeEnd在当前元素的后代中找到元素,则现在结束。

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

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