如何根据xml列表是否具有特定属性来过滤xml列表

时间:2015-10-12 13:25:53

标签: c# xml linq openxml

我一直试图将我的大脑包裹好几个小时。

我正在编写一个应用程序,它会删除word文档中的注释,并将其写入另一个文档的表中以供审核。作为一项要求,它需要包含注释来自何处的行引用,如果它是一个回复,则需要包含对父注释的引用。

我已经设法使用DocumentFormat.OpenXml库从word文档中找到所有3个文档部分。但是,当我试图收到回复评论时,我会陷入困境。

包含对注释及其父项的引用的XML如下

<w15:commentsEx xmlns:wpc="http://schemas.microsoft.com/office/word/2010/wordprocessingCanvas" xmlns:cx="http://schemas.microsoft.com/office/drawing/2014/chartex" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships" xmlns:m="http://schemas.openxmlformats.org/officeDocument/2006/math" xmlns:v="urn:schemas-microsoft-com:vml" xmlns:wp14="http://schemas.microsoft.com/office/word/2010/wordprocessingDrawing" xmlns:wp="http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing" xmlns:w10="urn:schemas-microsoft-com:office:word" xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main" xmlns:w14="http://schemas.microsoft.com/office/word/2010/wordml" xmlns:w15="http://schemas.microsoft.com/office/word/2012/wordml" xmlns:w16se="http://schemas.microsoft.com/office/word/2015/wordml/symex" xmlns:wpg="http://schemas.microsoft.com/office/word/2010/wordprocessingGroup" xmlns:wpi="http://schemas.microsoft.com/office/word/2010/wordprocessingInk" xmlns:wne="http://schemas.microsoft.com/office/word/2006/wordml" xmlns:wps="http://schemas.microsoft.com/office/word/2010/wordprocessingShape" mc:Ignorable="w14 w15 w16se wp14">
  <w15:commentEx w15:paraId="739FE385" w15:done="0" />
  <w15:commentEx w15:paraId="64E7F09D" w15:done="0" />
  <w15:commentEx w15:paraId="04DC26C3" w15:done="0" />
  <w15:commentEx w15:paraId="55A4D8B0" w15:paraIdParent="04DC26C3" w15:done="0" />
</w15:commentsEx>

现在我认为我的问题是因为它们都有命名空间,所以我必须使用where子句来获取属性的本地名称。例如

CommentsEx.Descendants().Where(x => x.Name.LocalName == "commentEx")

我有一个MyComment类型的列表,其中包含注释文本,作者,xmlId(xml中的paraId)以及对其父级的引用(xml中的paraIdParent),我现在想得到所有注释的列表有父母。我试过获取一个commentEx列表,然后调用以下linq语句

var replyComments = comment.Attributes()
                .Where(x => x.Name.LocalName == "paraIdParent").ToList();

但这只返回了一个属性列表,而不是包含该属性的commentEx列表。

如果我尝试获取属性的值,则会导致崩溃,因为所有标记上都不存在该属性。

所以我总结一下。我需要遍历commentsEx并寻找有父母的评论。然后,我需要使用属性paraId从我的列表中获取正确的注释,以便能够使用paraIdParent向父级添加链接。但我无法让它发挥作用。我使用的是错误的工具吗?我不应该使用linq吗?

2 个答案:

答案 0 :(得分:1)

我猜LINQ-to-XML会让你的任务变得轻而易举。您可以指定w15的命名空间以及节点名称。您可以使用XNamespace类: -

XDocument xdoc = XDocument.Load(@"YourXMLPath");
XNamespace ns = "http://schemas.microsoft.com/office/word/2012/wordml";
IEnumerable<XElement> replyComments = xdoc.Root.Elements(ns + "commentEx")
                    .Where(x => (string)x.Attribute(ns + "paraIdParent") != null);

<强>更新

您可以检查null,而(string)x.Attribute(ns + "paraIdParent")如果找不到属性,则会返回null

答案 1 :(得分:1)

尝试这样的事情:

var replyComments = (from comment in CommentsEx.Descendants()
                    where comment.Name.LocalName == "commentEx"
                    from attrib in comment.Attributes()
                    where attrib.Name.LocalName == "paraIdParent"
                    select comment).ToList();