我要做的是在CommentRangeStart
和相应的CommentRangeEnd
之间找到OpenXMLElements。
我尝试了两种方法来实现这一点,但问题是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 answer for dealing with elements between bookmark elements我复古适合我的例子,但仍然是开始和结束的问题拥有相同的父级(即在同一级别)是一个问题,我无法使用它。
有没有更好的方法来看待这个我正在寻找一种处理元素的方法,因为我需要使用正在评论的文本。
修改 澄清我想要实现的目标: 我正在使用文字编辑的文档和文档中的注释我希望获得在特定注释ID的开始和结束范围之间评论的文本。
编辑2: 我已经提出了我目前正在考虑的工作版本,但我的问题是它可能因为Word中的不同用户组合而非常脆弱。这也适用于xml,这不是一个真正的问题但可能希望更改为OpenXML SDK。目前看起来我需要解析整个文档来获取我需要的项目而不是使用1个特定注释。 https://github.com/mhbuck/DocumentCommentParser/
遇到的主要问题:CommentRangeStart
和CommentRangeEnd
可以位于XML文档中的不同嵌套中。根节点可能是唯一类似的祖先元素。
答案 0 :(得分: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
元素,它现在就结束了。
我还没有测试过这段代码,所以如果你有任何问题,请在评论中告诉我。
请注意,如果start元素在文档层次结构中比end元素更深,则此方法将不起作用。在某些情况下,它也不会返回评论中的一些内容。如果您需要它,我可以稍后使用替代解决方案更新答案来处理这种情况。还请解释为什么需要找到这些评论,因为可能会使用替代方法。