需要将 2 个 XML 中的属性合并为一个
本文关键字:合并 一个 属性 XML | 更新日期: 2023-09-27 18:32:44
我有两个这样的XML。
XML1
<RPM>
<CAI ID="101" Name="Guaranteed Payments"/>
<CAI ID="102" Name="Sports Recreation"/>
</RPM>
XML2
<RPM>
<CAI ID="102" Active="False"/>
<CAI ID="103" Active="True"/>
</RPM>
我必须编写一个 C# 代码,该代码将根据 CAI ID 将两个 XML 的属性合并为一个。例如,两个 XML 都有一个 CAI ID 为 102 的节点,因此最终的 XML 将是:
结果
<RPM>
<CAI ID="101" Name="Guaranteed Payments"/>
<CAI ID="102" Name="Sports Recreation" Active="False"/>
<CAI ID="103" Active="True"/>
</RPM>
我很想做这样的事情,将两个 XML 文件反序列化为类,然后通过代码将它们组合起来。
因此,XML 定义类将是您想要的最终产品:
[XmlTypeAttribute]
[XmlRootAttribute("RPM")]
public class RPMConfiguration
{
[XmlElementAttribute("CAI")]
public CAI[] CAIList{ get; set; }
}
[XmlTypeAttribute]
public class CAI
{
[XmlAttributeAttribute("ID")]
public int ID { get; set; }
[XmlAttributeAttribute("Name")]
public string Name { get; set; }
[XmlAttributeAttribute("Active")]
public string Active{ get; set; }
}
然后,您将像这样反序列化 xml 字符串:
public static object Deserialize(string xml)
{
var deserializer = new System.Xml.Serialization.XmlSerializer(typeof(RPMConfiguration));
using (var reader = XmlReader.Create(new StringReader(xml)))
{
return (RPMConfiguration)deserializer.Deserialize(reader);
}
}
此时,您有两个 RPMConfiguration 对象,其中包含一个 CAI 对象列表,然后您可以循环访问并匹配 ID 对象,将其中一个视为主集合,并将缺少的任何属性复制到其中。
一旦你完成。只需将配置序列化回XML,嘿,presto,一个完整的XML文件。
string xml1 = @"
<RPM>
<CAI ID=""101"" Name=""Guaranteed Payments""/>
<CAI ID=""102"" Name=""Sports Recreation""/>
</RPM>";
string xml2 = @"
<RPM>
<CAI ID=""102"" Active=""False""/>
<CAI ID=""103"" Active=""True""/>
</RPM>";
XDocument xDoc1 = XDocument.Load(new StringReader(xml1));
XDocument xDoc2 = XDocument.Load(new StringReader(xml2));
var cais = xDoc1.Descendants("CAI")
.Concat(xDoc2.Descendants("CAI"))
.GroupBy(x => x.Attribute("ID").Value)
.Select(x => x.SelectMany(y => y.Attributes()).DistinctBy(a => a.Name))
.Select(x => new XElement("CAI", x));
string xml = new XElement("RPM", cais).ToString();
你可以在这里找到Jon Skeet DistinctBy
的完整实现
public static partial class MyExtensions
{
public static IEnumerable<T> DistinctBy<T, TKey>(this IEnumerable<T> source, Func<T, TKey> keySelector)
{
HashSet<TKey> knownKeys = new HashSet<TKey>();
foreach (T element in source)
{
if (knownKeys.Add(keySelector(element)))
{
yield return element;
}
}
}
}