C# Linq-XElement比较
我尝试比较两个xelements(),如下所示: XElement父项=C# Linq-XElement比较,c#,linq,xelement,C#,Linq,Xelement,我尝试比较两个xelements(),如下所示: XElement父项= <tcm:ListItems xmlns:tcm="http://www.tridion.com/ContentManager/5.0"> <tcm:Item Title="070_Page" Modified="2016-01-06T18:08:36" CP1="-6185, Intro" CP2="-6182, Article Body" CP3="-14507, Article Body1" C
<tcm:ListItems xmlns:tcm="http://www.tridion.com/ContentManager/5.0">
<tcm:Item Title="070_Page" Modified="2016-01-06T18:08:36" CP1="-6185, Intro" CP2="-6182, Article Body" CP3="-14507, Article Body1" CP4="-14430, Article Body2" CP5="-14530, Article Body3" CP6="-7064, Article Body4" CP7="-14529, Article Body5" CP8="-7065, Article Body6" CPCount="8" />
<tcm:Item Title="080_Page" Modified="2015-04-23T13:27:59" CP1="-6302, Intro" CP2="-6193, Article Body" CPCount="2" />
<tcm:Item Title="Release Notes" Modified="2016-01-07T21:25:43" CP1="-6303, Release Notes Intro" CP2="-6196, Release Notes Article Body" CPCount="2" />
</tcm:ListItems>
XElement子项=
<tcm:ListItems xmlns:tcm="http://www.tridion.com/ContentManager/5.0">
<tcm:Item Title="070_Page" Modified="2016-06-06T19:36:35" CP1="-6185, Intro" CP2="-6147, Media & Delivery Intro" CP3="-6182, Article Body" CP4="-14507, Article Body1" CP5="-14430, Article Body2" CP6="-14530, Article Body3" CP7="-7064, Article Body4" CP8="-14529, Article Body5" CP9="-7065, Article Body6" CPCount="9" />
<tcm:Item Title="080_Page" Modified="2016-02-09T21:03:32" CP1="-6302, Intro" CP2="-6193, Article Body" CPCount="2" />
<tcm:Item Title="Release Notes" Modified="2016-02-09T21:03:33" CP1="-6303, Release Notes Intro" CP2="-6196, Release Notes Article Body" CPCount="2" />
<tcm:Item Title="Release Notes1" Modified="2016-03-09T22:00:13" CP1="-6303, Release Notes Intro" CP2="-6196, Release Notes Article Body" CPCount="2" />
</tcm:ListItems>
我希望我的结果是(第一个有不同的CPCount,第二个是childItems中的新元素):
像素差=
<tcm:ListItems xmlns:tcm="http://www.tridion.com/ContentManager/5.0">
<tcm:Item Title="070_Page" Modified="2016-06-06T19:36:35" CP1="-6185, Intro" CP2="-6147, Media & Delivery Intro" CP3="-6182, Article Body" CP4="-14507, Article Body1" CP5="-14430, Article Body2" CP6="-14530, Article Body3" CP7="-7064, Article Body4" CP8="-14529, Article Body5" CP9="-7065, Article Body6" CPCount="9" />
<tcm:Item Title="Release Notes1" Modified="2016-03-09T22:00:13" CP1="-6303, Release Notes Intro" CP2="-6196, Release Notes Article Body" CPCount="2" />
</tcm:ListItems>
我试过了,但运气不好。我可以循环并得到结果,但有时列表可能很大(3000+)。有没有最好的方法来处理这个问题?好的,下面是代码-在使用VS2015创建的控制台应用程序中(可能是非最佳的,但它可以工作-我最终得到了两个预期的元素-将重构作为家庭作业留给您):
类程序
{
//这只是为了方便地存储所有收集的数据
//还可以避免额外的字典查找和处理
内部类ElementAttributes
{
公共XElement元素{get;set;}
公共词典属性;
公共元素属性(XElement元素)
{
这个元素=元素;
this.Attributes=newdictionary();
}
}
静态void Main(字符串[]参数)
{
//从嵌入式资源加载XML元素
XElement parentItems=XElement.Parse(ResourceXML.parentItems);
XElement-childItems=XElement.Parse(ResourceXML.childItems);
XElement diff=XElement.Parse(@“”);
var parentDictionary=BuildDictionary(parentItems);
var childDictionary=BuildDictionary(childItems);
//执行差异
foreach(childDictionary.Keys中的字符串键)
{
元素属性parentElementAttributes;
if(parentDictionary.TryGetValue(键,out parentElementAttributes))
{
//在父级中找到标题/关键字,比较属性
foreach(childDictionary[key].Attributes中的var childAttribute)
{
var attributeName=childAttribute.Key;
var childAttributeValue=childAttribute.Value;
字符串parentAttributeValue;
if(parentElementAttributes.Attributes.TryGetValue(attributeName,out parentAttributeValue))
{
//在父级中找到属性,比较值
if(childAttributeValue==parentAttributeValue)
{
//值相等,比较其他属性
继续;
}
}
//父项没有此属性或
//子项中的不同值->在差异中显示
diff.Add(childDictionary[key].Element);
//不要比较其他属性
打破
}
//子级可能缺少仅在父级中的属性
//注意:您的示例没有提供此场景的用例
foreach(parentElementAttributes.Attributes中的var parentAttribute)
{
字符串attributeName=parentAttribute.Key;
如果(!childDictionary[key].Attributes.ContainsKey(attributeName))
{
//在父级中找到属性,但在子级中找不到
diff.Add(childDictionary[key].Element);
打破
}
}
}
其他的
{
//在父级中找不到,在差异中显示
diff.Add(childDictionary[key].Element);
}
}
}
私有静态字典构建字典(XElement元素)
{
XTCM=”http://www.tridion.com/ContentManager/5.0";
var resultDictionary=新字典();
foreach(element.Elements(tcm+“项”)中的XElement子元素)
{
var attributeDictionary=新元素属性(childElement);
foreach(childElement.Attributes()中的XAttribute属性)
{
字符串[]excludedColumns={“Title”,“Modified”};
if(excludedColumns.Contains(attribute.Name.LocalName))
{
继续;
}
attributeDictionary.Attributes.Add(attribute.Name.LocalName,attribute.Value);
}
resultDictionary.Add(childElement.Attribute(“Title”).Value,attributeDictionary);
}
返回结果字典;
}
}
所以您想使用Title属性作为键和其他属性-如果存在,只需进行比较,如果不匹配或缺少属性,则显示在结果列表中?您应该能够使用字典
,其中第一个键是元素标题,第二个键是要比较的属性名。建立其中的两个,左和右,然后比较。谢谢你。。。是,标题将是主过滤器。。其他属性可能不同。。但我的结果应该基于:1)CPCount 2)如果子元素中有一个新元素,而父字典中不存在,这是正确的方法吗?会不会有一场糟糕的表演。。。linq有类似deepequals的东西吗?我会在回家后研究这个问题,我会尝试为您制作一个工作代码示例。。。谢谢你
class Program
{
//this is just for convenient storage of all collected data
//also to avoid additional dictionary lookups and processing
internal class ElementAttributes
{
public XElement Element { get; set; }
public Dictionary<string, string> Attributes;
public ElementAttributes(XElement element)
{
this.Element = element;
this.Attributes = new Dictionary<string, string>();
}
}
static void Main(string[] args)
{
//loading XML elements from embedded resources
XElement parentItems = XElement.Parse(ResourceXML.parentItems);
XElement childItems = XElement.Parse(ResourceXML.childItems);
XElement diff = XElement.Parse(@"<tcm:ListItems xmlns:tcm=""http://www.tridion.com/ContentManager/5.0"" ></tcm:ListItems>");
var parentDictionary = BuildDictionary(parentItems);
var childDictionary = BuildDictionary(childItems);
//perform diff
foreach (string key in childDictionary.Keys)
{
ElementAttributes parentElementAttributes;
if (parentDictionary.TryGetValue(key, out parentElementAttributes))
{
//found Title/key in parent, compare attributes
foreach (var childAttribute in childDictionary[key].Attributes)
{
var attributeName = childAttribute.Key;
var childAttributeValue = childAttribute.Value;
string parentAttributeValue;
if (parentElementAttributes.Attributes.TryGetValue(attributeName, out parentAttributeValue))
{
//found attribute in parent, compare value
if(childAttributeValue == parentAttributeValue)
{
//values are equal, compare other attributes
continue;
}
}
//parent does not have this attribute OR
//different value in child -> show in diff
diff.Add(childDictionary[key].Element);
//do not compare other attributes
break;
}
//child may have missing attributes, which are in parent only
//NOTE: your example does not present a use case for this scenario
foreach (var parentAttribute in parentElementAttributes.Attributes)
{
string attributeName = parentAttribute.Key;
if (!childDictionary[key].Attributes.ContainsKey(attributeName))
{
//attribute found in parent, but not in child
diff.Add(childDictionary[key].Element);
break;
}
}
}
else
{
//not found in parent, show in diff
diff.Add(childDictionary[key].Element);
}
}
}
private static Dictionary<string, ElementAttributes> BuildDictionary(XElement element)
{
XNamespace tcm = "http://www.tridion.com/ContentManager/5.0";
var resultDictionary = new Dictionary<string, ElementAttributes>();
foreach (XElement childElement in element.Elements(tcm + "Item"))
{
var attributeDictionary = new ElementAttributes(childElement);
foreach (XAttribute attribute in childElement.Attributes())
{
string[] excludedColumns = {"Title", "Modified"};
if (excludedColumns.Contains(attribute.Name.LocalName))
{
continue;
}
attributeDictionary.Attributes.Add(attribute.Name.LocalName, attribute.Value);
}
resultDictionary.Add(childElement.Attribute("Title").Value, attributeDictionary);
}
return resultDictionary;
}
}