我有一个像这样的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>
我正在尝试查找重复的项目,然后再次使用像此
这样的逻辑复制子项目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 duplicateItems中),第一个项目就会丢失它的子项的上下文。第二个就好了。
例如,稍后在代码中我说
var allItemB = new List<XElement>();
foreach (duplicateItem in duplicateItems)
{
allItemB.AddRange(duplicateItem.Descendants("childB"));
}
我希望“allItemB”在第一遍中包含2,然后在第二遍中包含234。最终发生的事情是它只包含34,因为一旦枚举了duplicateItems数组,第一个XElement将丢失它的子项。
有谁知道如何解决这个问题?
答案 0 :(得分:2)
如果我理解你的问题,你想要allItemB有3个元素 - allItemB [0]是值为2的XElement childB,[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循环中更改了OrderBy,因为示例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") );