Csharp/C#教程:如何将具有不同名称但具有相同属性集的xml元素反序列化为类型化数组/集合分享


如何将具有不同名称但具有相同属性集的xml元素反序列化为类型化数组/集合

这是我试图反序列化的XML文件的一部分:

 ...  7  94 LPS 120 V 540 222 1758 W 400 mm 150 mm 1348 W 475 mm 1 Cooling <By Category> 108 108 50 VA   ...  ...   

这些是我用来反序列化它的类:

 [XmlType(AnonymousType = true)] [XmlRoot("entry", Namespace="https://www.w3.org/2005/Atom")] public class PartAtom { ... [XmlElement("family", Namespace="urn:schemas-autodesk-com:partatom")] public Family Family { get; set; } } public class Family { [XmlAttribute("type")] public string Type { get; set; } [XmlElement("variationCount")] public int VariationCount { get; set; } [XmlElement("part")] public FamilyType[] Parts { get; set; } } [XmlRoot(Namespace = "https://www.w3.org/2005/Atom")] public class FamilyType { [XmlAttribute("type")] public string Type { get; set; } [XmlElement("title")] public string Title { get; set; } [XmlArray] public Parameter[] Parameters { get; set; } } [XmlRoot(Namespace = "https://www.w3.org/2005/Atom")] public struct Parameter { [XmlAttribute("displayName")] public string Name { get; set; } [XmlAttribute("type")] public string Type { get; set; } [XmlAttribute("typeOfParameter")] public string DataType { get; set; } [XmlText] public string Value { get; set; } [XmlAttribute("units")] public string Units { get; set; } } 

我希望将诸如Voltage,Units_Length,Unit_Height,… Apparent_Load等元素反序列化为Parameters类的实例。 我怎么能做到这样的事情呢? 它甚至可能吗?

更新:

参数(标题下面的XML元素)几乎是无限的,所以我无法考虑所有这些参数,因此我必须手动指定XmlElement名称的所有算法都是不可用的。

如果您不想在类上实现IXmlSerializable ,则可以选择添加标有[XmlAnyElement]XElement []元素的代理属性,并将参数序列化到此列表中,并根据需要修复名称。

假设您的XML在根元素上具有名称空间声明,如下所示:

  

然后以下应该工作:

 [XmlType(Namespace = "https://www.w3.org/2005/Atom")] public class FamilyType { [XmlAttribute("type")] public string Type { get; set; } [XmlElement("title")] public string Title { get; set; } [XmlIgnore] public Parameter[] Parameters { get; set; } [XmlAnyElement] [Browsable(false), EditorBrowsable(EditorBrowsableState.Never), DebuggerBrowsable(DebuggerBrowsableState.Never)] public XElement[] XmlParameters { get { return XmlKeyValueListHelper.SerializeAttributeNameValueList(Parameters, "name"); } set { Parameters = XmlKeyValueListHelper.DeserializeAttributeNameValueList(value, "name"); } } } 

请注意,序列化程序会自动反序列化TitleType属性,而不是传递给AnyElement数组。 然后,在Parameter ,我将Name更改为DisplayName并添加了一个ElementName属性来保存元素名称:

 [XmlRoot(Namespace = "https://www.w3.org/2005/Atom")] public struct Parameter { [XmlAttribute("name")] public string ElementName { get; set; } // Added property. [XmlAttribute("displayName")] public string DisplayName { get; set; } // Changed from Name to DisplayName [XmlAttribute("type")] public string Type { get; set; } [XmlAttribute("typeOfParameter")] public string DataType { get; set; } [XmlText] public string Value { get; set; } [XmlAttribute("units")] public string Units { get; set; } } 

使用扩展和帮助方法:

 public static class XmlKeyValueListHelper { public static XElement[] SerializeAttributeNameValueList(IEnumerable items, string nameAttributeName) { if (items == null) return null; var ns = new XmlSerializerNamespaces(); ns.Add("", typeof(T).RootXmlElementNamespace()); var query = items .Select(p => p.SerializeToXElement(ns)) .Select(e => { var attr = e.Attribute(nameAttributeName); e.Name = e.Name.Namespace + XmlConvert.EncodeLocalName((string)attr); attr.Remove(); return e; }); return query.ToArray(); } public static T[] DeserializeAttributeNameValueList(IEnumerable elements, string nameAttributeName) { if (elements == null) return null; var query = elements .Select(e => new XElement(e)) // Do not modify the input values. .Select(e => { e.Add(new XAttribute(nameAttributeName, XmlConvert.DecodeName(e.Name.LocalName))); e.Name = e.Name.Namespace + typeof(T).RootXmlElementName(); return e; }) .Select(e => e.Deserialize()); return query.ToArray(); } } public static class XmlTypeExtensions { public static string RootXmlElementName(this Type type) { var xmlRoot = type.GetCustomAttribute(); if (xmlRoot != null && !string.IsNullOrEmpty(xmlRoot.ElementName)) return xmlRoot.ElementName; return type.Name; } public static string RootXmlElementNamespace(this Type type) { var xmlRoot = type.GetCustomAttribute(); if (xmlRoot != null && !string.IsNullOrEmpty(xmlRoot.Namespace)) return xmlRoot.Namespace; return string.Empty; } } public static class XObjectExtensions { static XmlSerializerNamespaces NoStandardXmlNamespaces() { var ns = new XmlSerializerNamespaces(); ns.Add("", ""); // Disable the xmlns:xsi and xmlns:xsd lines. return ns; } public static XElement SerializeToXElement(this T obj) { return obj.SerializeToXElement(null, NoStandardXmlNamespaces()); } public static XElement SerializeToXElement(this T obj, XmlSerializerNamespaces ns) { return obj.SerializeToXElement(null, ns); } public static XElement SerializeToXElement(this T obj, XmlSerializer serializer, XmlSerializerNamespaces ns) { var doc = new XDocument(); using (var writer = doc.CreateWriter()) (serializer ?? new XmlSerializer(obj.GetType())).Serialize(writer, obj, ns); var element = doc.Root; if (element != null) element.Remove(); return element; } public static T Deserialize(this XContainer element) { return element.Deserialize(new XmlSerializer(typeof(T))); } public static T Deserialize(this XContainer element, XmlSerializer serializer) { using (var reader = element.CreateReader()) { object result = serializer.Deserialize(reader); if (result is T) return (T)result; } return default(T); } } 

仍然比定制的IXmlSerializable更容易。

这样做的一种(丑陋)方式可能是在对其进行反序列化之前修改XML。 只需将所有“Voltage”,“Unit_height”等字符串替换为“YourParameterClassName”。 然后他们应该很好地反序列化,我猜你的“typeOfParameter”仍然会提供与更换之前节点中最初存在的信息相同的信息。

一个解决方案可能是指定了不同名称的多个XmlElementAttribute 。如下所示:

上述就是C#学习教程:如何将具有不同名称但具有相同属性集的xml元素反序列化为类型化数组/集合分享的全部内容,如果对大家有所用处且需要了解更多关于C#学习教程,希望大家多多关注—计算机技术网(www.ctvol.com)!

  [XmlElement("Voltage")] [XmlElement("Unit_Height")] [XmlElement("Supply_Air_Height")] [XmlElement("CFU_Material")] 

本文来自网络收集,不代表计算机技术网立场,如涉及侵权请联系管理员删除。

ctvol管理联系方式QQ:251552304

本文章地址:https://www.ctvol.com/cdevelopment/953295.html

(0)
上一篇 2021年11月19日
下一篇 2021年11月19日

精彩推荐