There is xml . As I understand it, to make class elements with the attributes atr1, atr2 ... is wrong, because if there are more of them and with different id, you will have to create many more properties.

 <root> <tag atr1 = "value"/> <tag atr2 = "value"/> <tag3>value</tag3> </root> 

Question. How to make so that we can set an attribute with any number

Built-in generator gave some sort of porridge

 /// <remarks/> [System.SerializableAttribute()] [System.ComponentModel.DesignerCategoryAttribute("code")] [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)] [System.Xml.Serialization.XmlRootAttribute(Namespace = "", IsNullable = false)] public partial class root { private rootTag[] tagField; private string tag3Field; /// <remarks/> [System.Xml.Serialization.XmlElementAttribute("tag")] public rootTag[] tag { get { return this.tagField; } set { this.tagField = value; } } /// <remarks/> public string tag3 { get { return this.tag3Field; } set { this.tag3Field = value; } } } /// <remarks/> [System.SerializableAttribute()] [System.ComponentModel.DesignerCategoryAttribute("code")] [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)] public partial class rootTag { private string atr1Field; private string atr2Field; /// <remarks/> [System.Xml.Serialization.XmlAttributeAttribute()] public string atr1 { get { return this.atr1Field; } set { this.atr1Field = value; } } /// <remarks/> [System.Xml.Serialization.XmlAttributeAttribute()] public string atr2 { get { return this.atr2Field; } set { this.atr2Field = value; } } } 
  • How to create a class for a given xml is the question. - Radzhab
  • The structure of your xml rather strange, you do not have the opportunity to change it? - user227049
  • That's the point - to deserialize such XML - Radzhab

2 answers 2

if there are more of them with other id

If the number in the names of attributes and elements is id , then you need to revise the xml generation scheme itself. Do something like this:

 <tag id="1" atr="value"/> <tag id="2" atr="value"/> 

Or so, if the content is complex:

 <tag id="1">complex value</tag> <tag id="2">complex value</tag> 

For such xml, the set of C # classes is simple and logical.


Perhaps the easiest way to use the following class:

 public class Tag { public string Attr { get; set; } } 

and parse the xml using linq:

 var xml = XElement.Load("test.xml"); // Выбираем все элементы, начинающиеся с tag var tagElements = xml.Elements() .Where(elem => elem.Name.LocalName.StartsWith("tag")); // Создаём список объектов класса Tag, свойство Attr которого // будет заполнено значением атрибута atr{n} или равно null var tags = tagElements.Select(elem => new Tag { Attr = elem.Attributes() .FirstOrDefault(attr => attr.Name.LocalName.StartsWith("atr"))?.Value }) .ToList(); 

Notice the use of the null-conditional ?. Operator ?. (it is also called Elvis).


If you still really want to use deserialization, then there are several different ways: implement the IXmlSerializable interface, write a custom XmlReader or use the events of the serializer itself.

I will show how to apply the latter approach.

The set of classes may be different. For example, create this:

 [XmlRoot("root")] public class Root { [XmlElement("tag")] public List<Tag> Tags { get; set; } } public class Tag { [XmlAttribute("atr")] public string Attr { get; set; } } 

When creating a serializer, let's sign it for events:

 var xs = new XmlSerializer(typeof(Root)); xs.UnknownElement += Xs_UnknownElement; xs.UnknownAttribute += Xs_UnknownAttribute; 

These events occur when unknown elements and attributes are encountered in xml. In the code of the event handlers, we manually read the values ​​of the elements or nodes and write them to our instances of the objects.

 private static void Xs_UnknownAttribute(object sender, XmlAttributeEventArgs e) { Tag tag = (Tag)e.ObjectBeingDeserialized; tag.Attr = e.Attr.Value; } private static void Xs_UnknownElement(object sender, XmlElementEventArgs e) { Root root = (Root)e.ObjectBeingDeserialized; Tag tag = new Tag(); tag.Attr = e.Element.InnerText; root.Tags.Add(tag); } 

Usage as usual:

 Root root; using (var fs = new FileStream("test.xml", FileMode.Open)) root = (Root)xs.Deserialize(fs); 

    I think that it is impossible to do this through a standard deserializer, since XML is superimposed on a specific class that will contain XML values.

    Therefore, in my opinion, there are 2 options:

    1. Through the reader to read the nodes fill the object as you want.

    2. Write your own deserializer.