2013-03-05 175 views
1

我有下面的XML:的LINQ to XML子查询

<Event ID="1"..... > 
    <SubEvent update="DATETIME" /> 
    <SubEvent update="DATETIME" /> 
    <SubEvent update="DATETIME" /> 
    <SubEvent update="DATETIME" /> 
    <SubEvent update="DATETIME" /> 
    <SubEvent update="DATETIME" /> 
</Event> 
<Event ID="2"..... > 
    <SubEvent update="DATETIME" /> 
    <SubEvent update="DATETIME" /> 
    <SubEvent update="DATETIME" /> 
    <SubEvent update="DATETIME" /> 
    <SubEvent update="DATETIME" /> 
    <SubEvent update="DATETIME" /> 
</Event> 
<Event ID="3"..... > 
    <SubEvent update="DATETIME" /> 
    <SubEvent update="DATETIME" /> 
    <SubEvent update="DATETIME" /> 
    <SubEvent update="DATETIME" /> 
    <SubEvent update="DATETIME" /> 
    <SubEvent update="DATETIME" /> 
</Event> 

我想删除“事件”元素,其中的子事件全部更新属性比提供DATETIME低。

如果例如一个DATETIME较高,则不应删除该元素。

+0

为什么你觉得呢?你觉得它太慢了吗? – 2013-03-05 13:47:48

+2

你认为LINQ to XML如何工作?有魔力? :)它也遍历元素。 – 2013-03-05 13:50:19

+0

我意识到我的最后一条评论可能没有帮助你,所以这里有一些额外的建议:尽量减少循环。例如,如果“Event”的第一个“SubEvent”大于提供的日期,则可以停止处理该“Event”。没有必要遍历剩余的SubEvent元素。但除此之外,你可以做的不多。 – 2013-03-05 13:57:54

回答

3

简单地选择所有这些事件,并从文件中删除:

DateTime date = DateTime.Now; 
XDocument xdoc = XDocument.Load(path_to_xml); 
xdoc.Descendants("Event") 
    .Where(e => e.Elements().All(se => (DateTime)se.Attribute("update") < date)) 
    .Remove(); 
xdoc.Save(path_to_xml); 

正常工作与下面的XML:

<?xml version="1.0" encoding="utf-8" ?> 
<Events> 
    <Event ID="1" > 
    <SubEvent update="2013-02-05T17:06:23.8962976+03:00" /> 
    <SubEvent update="2013-03-08T17:06:23.8962976+03:00" /> 
    </Event> 
    <Event ID="2"> 
    <SubEvent update="2013-01-05T17:06:23.8962976+03:00" /> 
    <SubEvent update="2013-01-05T17:06:23.8962976+03:00" /> 
    <SubEvent update="2013-02-05T17:06:23.8962976+03:00" /> 
    </Event> 
    <Event ID="3"> 
    <SubEvent update="2013-03-05T17:06:23.8962976+03:00" /> 
    <SubEvent update="2013-04-05T17:06:23.8962976+03:00" /> 
    </Event> 
</Events> 
+0

我很好奇为什么在你的示例''删除'工作正常,但是当我在'我的foreach'像'el.Remove()'它只适用于第一个元素? – aush 2013-03-05 14:10:28

+0

@aush坚持,我会检查 – 2013-03-05 14:12:33

+1

@aush看起来像枚举中断时修改文档。如果你将在foreach语句中执行'query.ToList()',那么所有的都会正常工作。如果你不会删除元素(只是枚举,那么一切都很好)。你可能想知道为什么它可以与'Enumerable '扩展一起使用? :)因为内部还创建了新的元素列表:'foreach(T本地新列表(源))' – 2013-03-05 14:27:12

0

在想你是不会错过你的XML

var xDoc = // your XDocument 
var toDel = new List<XElement>(); 
foreach(var el in xDoc.Root.Elements("Event").Where(e => e.Elements("SubEvent").All(xel => xel.Attribute("update").Value == "DATETIME"))) 
{ 
    toDel.Add(el); 
} 
toDel.ForEach(e => e.Remove()); 

的根必须更换的条件内.All()到理想的。

0

试试这个:

 var doc = XDocument.Load(@"D:\input.xml"); 
     var x = new List<XElement>(); 
     foreach (var xElement in doc.Root.Elements("Event")) 
     { 
      DateTime maxDt = DateTime.MinValue; 

      foreach (var element in xElement.Elements("SubEvent")) 
      { 
       var attributeValue = element.Attributes("update").FirstOrDefault(); 

       if (attributeValue == null) continue; 

       DateTime dt; 
       if (!DateTime.TryParse(attributeValue.Value, out dt)) continue; 

       if (maxDt < dt) maxDt = dt; 
      } 

      xElement.RemoveNodes(); 
      xElement.Add(new XElement("SubEvent", new XAttribute("update", maxDt.ToString("yyyy-MM-dd HH:mm:ss")))); 
      x.Add(new XElement(xElement)); 

     } 

     new XDocument(new XElement("ev", x)).Save(@"D:\output.xml");