2015-05-20 35 views
0

xml树需要根据属性进行过滤。子元素与父元素具有相同的名称。如果满足显示元素的标准,则需要显示此元素和所有父级结构。如何根据子属性过滤XDocument并保留父结构?

例如在xml样子(深度级别是随机的):

<Root> 
    <Foo attr="xyz 123"></Foo> 
    <Foo attr="abc 111"></Foo> 
    <Foo attr="abc 222"> 
     <Foo attr="abc 111"></Foo> 
     <Foo attr="abc 222"> 
      <Foo attr="xyz 123"></Foo> 
     </Foo> 
    </Foo> 
</Root> 

过滤准则是,该属性 “ATTR” 包含文本 “XYZ”。过滤后的xml应该像:

<Root> 
    <Foo attr="xyz 123"></Foo> 
    <Foo attr="abc 222"> 
     <Foo attr="abc 222"> 
      <Foo attr="xyz 123"></Foo> 
     </Foo> 
    </Foo> 
</Root> 

XDocument用于保持树结构(后XDocument_instance.Elements()连接到WPF树视图)。

以下LINQ的命令执行排序只有第一元素水平(根后):

var Elements = from el in xdoc.Root.Elements() 
       where 
        el.Attribute("attr").Value.Contains("xyz") 
       select el 

如何创建一个LINQ命令(或foreach循环),这将应用描述的滤波?

编辑: 一个首选的解决方案不会修改原始数据,但会为视图创建另一个(即Linq查询)。

回答

1
// first make a list of elements that are to be removed 
var forRemoval = new List<XElement>(); 
foreach (var element in xmlDoc.Descendants()) 
{ 
    if (!element.DescendantsAndSelf().Any(e => e.Attribute("attr") != null && e.Attribute("attr").Value.Contains("xyz"))) 
    { 
     forRemoval.Add(element); 
    } 
} 

// then remove the elements 
foreach (var xElement in forRemoval) 
{ 
    xElement.Remove(); 
} 
+0

这是一个非常好的解决方法,但它修改了原始树。对不起,我没有在问题中指明。我必须在过滤之前进行深层复制(因为稍后可能会应用另一个过滤器)。一个首选的解决方案是Linq查询。 – bitman

0

您需要Descendants(),将得到的文档中的所有子元素:

var Elements = from el in xdoc.Root.Descendants() 
       where 
        el.Attribute("attr").Value.Contains("xyz") 
       select el 
+0

谢谢,但这并不保留树结构。 – bitman

0

您可以使用下面的LINQ:

var Elements = from el in xdoc.Root.Elements() 
       where (el.Attribute("attr") != null && el.Attribute("attr").Value.Contains("xyz")) || 
        (el.Descendants().Any(x => x.Attribute("attr") != null && x.Attribute("attr").Value.Contains("xyz"))) 
       select el; 
+0

如果您使用'DescendantsAndSelf',则不必重复标准。 – paul

+0

我试图做同样的事情,但'DescendantsAndSelf'返回'XNode'和'XNode'的集合,我还没有找到任何访问属性的方法/ Proerty。所以我做到了。 –

+0

一个非常好的尝试,但它不回答这个问题。该查询仅删除顶层的元素。但是,即保留了。如果元素不符合过滤标准,请参阅必须移除/保留元素的示例。 – bitman