我有多个 XML 文件,我正试图合并到一个文件中。 Linq to XML 可能是最好的选择,但我对想法持开放态度(XSLT 似乎擅长合并两个文件,但在 n > 2 或 n = 大的情况下很笨拙)。
从这里阅读其他问题,某种连接看起来不错。
文件1.xml:
<first>
<second>
<third id="Id1">
<values>
<value a="1" b="one"/>
<value a="2" b="two"/>
<value a="3" b="three"/>
</values>
</third>
<third id="Id2">
<values>
<value a="f" b="foo"/>
<value a="b" b="bar"/>
<value a="w" b="wibble"/>
</values>
</third>
</second>
</first>
文件2.xml:
<first>
<second>
<third id="Id1">
<values>
<value a="2" b="two"/>
<value a="3" b="three"/>
<value a="6" b="six"/>
</values>
</third>
<third id="Id3">
<values>
<value a="x" b="ex"/>
<value a="y" b="why"/>
<value a="z" b="zed"/>
</values>
</third>
</second>
</first>
合并.xml:
<first>
<second>
<third id="Id1">
<values>
<value a="1" b="one"/>
<value a="2" b="two"/>
<value a="3" b="three"/>
<value a="6" b="six"/>
</values>
</third>
<third id="Id2">
<values>
<value a="f" b="foo"/>
<value a="b" b="bar"/>
<value a="w" b="wibble"/>
</values>
</third>
<third id="Id3">
<values>
<value a="x" b="ex"/>
<value a="y" b="why"/>
<value a="z" b="zed"/>
</values>
</third>
</second>
</first>
即它根据第三个/@id 属性合并值。
我如何使用 linq 优雅地做到这一点?
最佳答案
下面仍然很丑陋,我相信可以通过一些工作将它变成更流线型的形状,但现在这似乎可以完成工作:
public static void MergeXml()
{
var xdoc1 = XDocument.Load(@"c:\temp\test.xml");
var xdoc2 = XDocument.Load(@"c:\temp\test2.xml");
var d1Targets = xdoc1.Descendants("third");
var d2Selection = xdoc2.Descendants("third").ToList();
Func<XElement, XElement, string, bool> attributeMatches = (x, y, a) =>
x.Attribute(a).Value == y.Attribute(a).Value;
Func<IEnumerable<XElement>, XElement, bool> hasMatchingValue = (ys, x) =>
// remove && if matching "a" should cause replacement.
ys.Any(d => attributeMatches(d, x, "a") && attributeMatches(d, x, "b"));
foreach (var e in d1Targets)
{
var fromD2 = d2Selection.Find(x => attributeMatches(x, e, "id"));
if (fromD2 != null)
{
d2Selection.Remove(fromD2);
var dest = e.Descendants("value");
dest.LastOrDefault()
.AddAfterSelf(fromD2.Descendants("value").Where(x => !hasMatchingValue(dest, x)));
}
};
if (d2Selection.Count > 0)
d1Targets.LastOrDefault().AddAfterSelf(d2Selection);
xdoc1.Save(@"c:\temp\merged.xml");
}
这会从 OPs 问题中的两个示例输入文件生成以下输出文件:
<?xml version="1.0" encoding="utf-8"?>
<first>
<second>
<third id="Id1">
<values>
<value a="1" b="one" />
<value a="2" b="two" />
<value a="3" b="three" />
<value a="6" b="six" />
</values>
</third>
<third id="Id2">
<values>
<value a="f" b="foo" />
<value a="b" b="bar" />
<value a="w" b="wibble" />
</values>
</third>
<third id="Id3">
<values>
<value a="x" b="ex" />
<value a="y" b="why" />
<value a="z" b="zed" />
</values>
</third>
</second>
</first>
关于c# - 使用linq合并具有相同结构的多个XML文件并根据键删除重复项,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29802221/