1

Xml example:

<Profile>
  <ProfileSections>
    <ProfileSection Name="Default">
      <Email>[email protected]</Email>
      <Pasword>test</Pasword>
    </ProfileSection>
    <ProfileSection Name="Address">
      <Street>Undermissed</Street>
    </ProfileSection>
  </ProfileSections>
</Profile>

How to deserialize this XML to have List ProfileSections and each profile section to necessary object? Object examples:

public class DefaultProdileSection{
        [XmlAttribute]
        public string Name{ get; set; }
        public string Email{ get; set; }
        public string PAssword{ get; set; }
}

public class AddressProdileSection{
            [XmlAttribute]
            public string Name{ get; set; }
            public string Street{ get; set; }
 }
6
  • Does this answer your question? How to Deserialize XML document Commented Apr 25, 2022 at 13:11
  • 1
    @pritaeas Unfortunately, no. The problem is that types of objects in ProfileSections are different and I do not know how to define which type to use during deserialization. Usually it's 'type' tag, but there is no such tag in my xml. Commented Apr 25, 2022 at 13:25
  • 'type' attribute, not tag Commented Apr 25, 2022 at 13:31
  • 2
    Easiest thing is probably to deserialize <ProfileSection> to some DTO with all possible properties, and then postprocess into your class hierarchy after deserialization. Can you infer the schema for the <ProfileSection Name="xxx"> elements from the value for the Name element? Does the name attribute have some fixed set of values? Commented Apr 25, 2022 at 13:34
  • Seems yes, the easiest way. Commented Apr 25, 2022 at 13:55

1 Answer 1

1

We can manually add a type attribute to the xml token stream when parsing.

If you really really want to use deserialization, then I can suggest the following code.

Set of classes:

public class Profile
{
    public List<ProfileSection> ProfileSections { get; set; }
}

[XmlInclude(typeof(DefaultProfileSection))]
[XmlInclude(typeof(AddressProfileSection))]
public class ProfileSection
{
    [XmlAttribute]
    public string Name { get; set; }
}

public class DefaultProfileSection : ProfileSection
{
    public string Email { get; set; }
    public string Password { get; set; }
}

public class AddressProfileSection : ProfileSection
{
    public string Street { get; set; }
}

A custom xml reader that will add the necessary information on the fly:

public class TypeAddingXmlReader : XmlTextReader
{
    public TypeAddingXmlReader(string url) : base(url) { }

    // Define the remaining constructors here

    public override string? GetAttribute(string localName, string? namespaceURI)
    {
        if (base.LocalName == "ProfileSection" &&
            localName == "type" &&
            namespaceURI == "http://www.w3.org/2001/XMLSchema-instance")
        {
            var name = base.GetAttribute("Name");

            return name switch
            {
                "Default" => nameof(DefaultProfileSection),
                "Address" => nameof(AddressProfileSection)
                // add other class names here
            };
        }

        return base.GetAttribute(localName, namespaceURI);
    }
}

Use:

var ser = new XmlSerializer(typeof(Profile));

using var reader = new TypeAddingXmlReader("test.xml");

var profile = (Profile)ser.Deserialize(reader);

foreach (var ps in profile.ProfileSections)
    Console.WriteLine(ps.Name + " " + ps.GetType());

Namespaces:

using System.Xml;
using System.Xml.Serialization;

Note: but I would use linq to xml and not sweat it.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.