我有两个XML文件(* .resx文件),我试图合并到一个删除重复项,但我无法这样做。我试过以下但没有取得任何成功:
var resource1 = XDocument.Load("C:\\Resources.resx");
var resource2 = XDocument.Load("C:\\Resources2.resx");
// This results in a file with all the nodes from the second file included inside
// the root element of the first file to form a properly formatted, concatenated file.
resource1.Descendants().FirstOrDefault().Add(resource2.Descendants().FirstOrDefault().Nodes());
var nodeContent = new List<string>();
foreach (XElement node in resource1.Root.Elements())
{
if (nodeContent.Contains(node.ToString()))
resource1.Remove();
else
nodeContent.Add(node.ToString());
}
resource1.Save("C:\\FinalResources.resx");
在remove语句中,我得到一个InvalidOperationException - “父项缺失。”:
我做错了吗?
答案 0 :(得分:2)
您需要定义一个EqualityComparer<XElement>
,以便您使用标准的LINQ运算符。
所以,作为一个简单的例子我创建了这个:
public class ElementComparer : EqualityComparer<XElement>
{
public override int GetHashCode(XElement xe)
{
return xe.Name.GetHashCode() ^ xe.Value.GetHashCode();
}
public override bool Equals(XElement xe1, XElement xe2)
{
var @return = xe1.Name.Equals(xe2.Name);
if (@return)
{
@return = xe1.Value.Equals(xe2.Value);
}
return @return;
}
}
然后我可以从这两个XML文档开始:
<xs>
<x>D</x>
<x>A</x>
<x>B</x>
</xs>
<xs>
<x>E</x>
<x>B</x>
<x>C</x>
</xs>
这样做:
var xml1 = XDocument.Parse(@"<xs><x>D</x><x>A</x><x>B</x></xs>");
var xml2 = XDocument.Parse(@"<xs><x>E</x><x>B</x><x>C</x></xs>");
xml1.Root.Add(
xml2.Root.Elements("x")
.Except(xml1.Root.Elements("x"), new ElementComparer()));
然后xml1
将如下所示:
<xs>
<x>D</x>
<x>A</x>
<x>B</x>
<x>E</x>
<x>C</x>
</xs>
答案 1 :(得分:1)
嗯,最直接的方式是:
var resource1 = XDocument.Load("C:\\Resources.resx");
var resource2 = XDocument.Load("C:\\Resources2.resx");
foreach (XElement node in resource2.Root.Elements())
{
if (resource1.Root.Contains(node)) continue;
resource1.Add(node);
}
resource1.Save("C:\\FinalResources.resx");
public static class XElementExtensions
{
public static bool Contains(this XElement root, XElement e)
{
//or w/e equality logic you need
return root.Elements().Any(x => x.ToString().Equals(e.ToString()));
}
}
这只会合并第一级条目。如果需要深度合并,则必须设置一个简单的递归(对子元素使用相同的循环)。
答案 2 :(得分:0)
resource1.Remove();被调用两次,它的作用是删除根元素。所以第二次不再有一个根元素要删除,从而抛出异常。