我有两个不同的XML,结构如下:
XML 1:
<function>
<subfunction id="s1" value="s1">
<display id="1" value="a"></display>
<display id="2" value="b"></display>
<display id="3" value="c"></display>
<display id="4" value="d"></display>
</subfunction>
</function>
XML 2:
<function>
<subfunction id="s1" some-value="other">
<display id="1" another-data="something"></display>
<display id="2" another-data="something"></display>
<display id="3" another-data="something"></display>
<display id="4" another-data="something"></display>
</subfunction>
</function>
我想合并这两个XML,所以最终输出如下所示:
<function>
<subfunction id="s1" value="s1" some-value="other">
<display id="1" value="a" another-data="something"></display>
<display id="2" value="b" another-data="something"></display>
<display id="3" value="c" another-data="something"></display>
<display id="4" value="d" another-data="something"></display>
</subfunction>
</function>
目前我在C#中使用forEach循环来合并这两个非常低效的XML。有没有其他方法可以一次执行此操作?
我正在使用以下代码进行合并
public XmlDocument MergeXMLAttributes(XmlDocument doc, XmlDocument trimmedXmlDoc)
{
var nodes = trimmedXmlDoc.DocumentElement.SelectNodes("//*");
foreach (XmlElement displayNode in nodes)
{
var nodeId = displayNode.GetAttribute("id");
var nodeXPath = String.Format("//*[@id='{0}']", nodeId);
XmlElement fullNode = doc.SelectSingleNode(nodeXPath) as XmlElement;
foreach (XmlAttribute attribute in displayNode.Attributes)
{
fullNode.SetAttribute(attribute.Name, attribute.Value);
}
}
return doc;
}
答案 0 :(得分:1)
static void Main(string[] args)
{
var xml1 = XElement.Parse(@"<function>
<subfunction id=""s1"" value=""s1"">
<display id=""1"" value=""a""></display>
<display id=""2"" value=""b""></display>
<display id=""3"" value=""c""></display>
<display id=""4"" value=""d""></display>
</subfunction>
</function>");
var xml2 = XElement.Parse(@"<function>
<subfunction id=""s1"" some-value=""other"">
<display id=""1"" another-data=""something""></display>
<display id=""2"" another-data=""something""></display>
<display id=""3"" another-data=""something""></display>
<display id=""4"" another-data=""something""></display>
</subfunction>
</function>");
var xml3 = Merge(xml1, xml2);
Console.WriteLine(xml3.ToString());
Console.ReadLine();
}
private static XElement Merge(XElement thisElement, XElement otherElement)
{
if(thisElement.Name == otherElement.Name)
{
var merged = new XElement(thisElement.Name);
merged.ReplaceAttributes(Attributes(thisElement, otherElement).ToArray());
var thisChildren = thisElement.Elements().Where(e => e.Attribute("id") != null);
if(thisChildren.Any())
{
var children = thisChildren.Select(thisChild => {
var otherChild = otherElement
.Elements()
.Where(e => e.Attribute("id") != null && e.Attribute("id").Value == thisChild.Attribute("id").Value)
.FirstOrDefault();
if(otherChild != null)
{
return Merge(thisChild, otherChild);
}
return null;
}).Where(child => child != null);
merged.Add(children.ToArray());
}
return merged;
}
return null;
}
private static IEnumerable<XAttribute> Attributes(XElement thisElement, XElement otherElement)
{
return thisElement
.Attributes()
.Concat(otherElement.Attributes())
.GroupBy(a => a.Name)
.Select(g => g.FirstOrDefault())
.Where(a => a != null);
}