2012-07-07 73 views
0

丢了,我有这样的LINQ的XML后裔正在对枚举

<root> 
    <item id="1" creator="me"> 
    <childA>1</childA> 
    <childB>2</childB> 
    </item> 
    <item id="2" creator="me"> 
    <childA>1</childA> 
    <childB>3</childB> 
    <childB>4</childB> 
    </item> 
</root> 

一个XML文档我试图找到重复的项目,然后再复制的重复项目子项的逻辑是这样

XDocument XmlRoot //whatever...you get the point 

// Get item nodes 
var items = XmlRoot.Descendants("item"); 

// Find duplicate items keys using creator attribute 
var duplicateItemKeys = items.GroupBy(x => x.Attribute("creator").Value) 
.Where(g => g.Count() > 1) 
.Select(g => g.Key); 

foreach(var duplicateItemKey in duplicateItemKeys) 
{ 
    // Get the duplicate item XML elements using the duplicate keys 
    var duplicateItems = items.Where(x => x.Attribute("creator").Value == duplicateToucheKey) 
     .OrderBy(xelement => xelement.Attribute("CreatedOn").Value); 
} 

这工作,但有一个问题后,当我尝试使用duplicateItems。任何时候它枚举(就像在一个foreach重复项),第一项失去了它的孩子的上下文。第二个就好了。

因此,例如,在后面的代码我说

var allItemB = new List<XElement>(); 
foreach (duplicateItem in duplicateItems) 
{ 
    allItemB.AddRange(duplicateItem.Descendants("childB")); 
} 

我想到“allItemB”包含在第一轮2,那么234在第二。什么最终发生的是,它仅包含34因为一旦duplicateItems阵列枚举的第一个的XElement失去它的孩子。

有谁知道如何解决这一问题?

+0

什么是第一部分的期望的结果?它是作为一个XElement保留还是可以作为'孩子'字典,'连接值'? – 2012-07-07 14:40:23

+0

理想情况下,我试图解析为重复的XML,然后再组装起来,并将其发送回数据库。 – farina 2012-07-10 16:43:43

+0

什么被认为是重复的?重复的标签名称,值,属性名称,属性值? – 2012-07-10 17:33:45

回答

2

如果我正确理解你的问题,你想allItemB有3个要素 - allItemB [0]是的XElement childB值为2,[1]为3和[2]为4?

如果是这样,问题是你在哪里声明duplicateItems。你的代码甚至不会编译,因为变量的作用域限于第一个foreach循环,因此在第二个循环中不可用。

我的代码,以获得上述结果:

XDocument XmlRoot = XDocument.Load("C:\\somefile.xml"); 

// Get item nodes 
var items = XmlRoot.Descendants("item"); 

// Find duplicate items keys using creator attribute 
var duplicateItemKeys = items.GroupBy(x => x.Attribute("creator").Value) 
    .Where(g => g.Count() > 1) 
    .Select(g => g.Key); 

IEnumerable<XElement> duplicateItems = new List<XElement>(); 
foreach(var duplicateItemKey in duplicateItemKeys) 
{ 
    // Get the duplicate item XML elements using the duplicate keys 
    duplicateItems = items.Where(x => x.Attribute("creator").Value == duplicateItemKey) 
      .OrderBy(xelement => xelement.Attribute("id").Value); 
} 

var allItemB = new List<XElement>(); 
foreach (var duplicateItem in duplicateItems) 
{ 
     allItemB.AddRange(duplicateItem.Descendants("childB")); 
} 

编辑:忘了提,我改变了排序依据第一foreach循环,因为样本XML文件没有足够的CreatedOn属性。

如果你愿意,你可以使用多一点的LINQ,丢弃的foreach循环完全,像这样:

XDocument XmlRoot = XDocument.Load("C:\\somefile.xml"); 

// Get item nodes 
var items = XmlRoot.Descendants("item"); 

// Find duplicate items keys using creator attribute 
var duplicateItemKeys = items.GroupBy(x => x.Attribute("creator").Value) 
    .Where(g => g.Count() > 1) 
    .Select(g => g.Key); 

// Get the duplicate item XML elements using the duplicate keys 
var duplicateItems = items.Where(i => duplicateItemKeys.Contains(i.Attribute("creator").Value)) 
    .OrderBy(xelement => xelement.Attribute("id").Value); 

// Get the child nodes named childB 
var allItemB = new List<XElement>(); 
allItemB.AddRange(duplicateItems.Descendants("childB")); 
+0

是的,我的代码没有编译,因为我错误地复制和一些其他的代码粘贴。对于那个很抱歉。我不能相信我没有注意到我的duplicateItems var的范围不正确!我觉得自己像个傻瓜。谢谢您的帮助! – farina 2012-07-10 20:22:54