ExtendedXmlSerializer / home

A configurable and eXtensible Xml serializer for .NET.

Home Page:https://extendedxmlserializer.github.io/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

How to create a Xml document with same class, different structures with C#?

aGreefa opened this issue · comments

I have to create a XML structure but dont know how to do this. I have in one xml document two different structures with the same class. The first structure shows a structure that element is a List of . Also element is a list from itself.

The second structure shows that element Member also a List is from . These two structures must generated in one xml document. If I create a another class that is a List and give the Xmlroot with the name "Member", the Xml-Generator give an exception that soms classes have the same name. Can anyone help me to solve this? How to get the structure of Subelements also in these classes?

First structure
image

Second structure
image

The code of the classes what I now have is:

public class Section : List<Member>
{
    public Section() {}
       
    public Section(string aName)
    {
      Name = aName;
    }

    [XmlAttribute] public string Name { get; set; }
}


 public class Member : List<Member>
  {
    public Member()
    {
    }

    public Member(string aName, string aDatatype, string aRemanence)
    {
      Name = aName;
      Datatype = aDatatype;
      Remanence = aRemanence;
      Sections = new List<Section>();
    }

    public Member(string aName, string aDatatype, string aAccessibility, string aRemanence)
    {
      Name = aName;
      Datatype = aDatatype;
      Accessibility = aAccessibility;
      Remanence = aRemanence;
    }

    [XmlAttribute] public string Name { get; set; }
    [XmlAttribute] public string Datatype { get; set; }
    [XmlAttribute] public string Accessibility { get; set; }
    [XmlAttribute] public string Remanence { get; set; }

    public List<Section> Sections { get; set; }

    [XmlArrayItem("BooleanAttribute")]
    public bool[] AttributeList{ get; set; }
    public string StartValue { get; set; }

    [XmlArrayItem("MultiLanguageText")]
    public string[] Comment { get; set; }
}

Hi @aGreefa thank you for writing in with your question. I am a little confused however by what you mean by "Xml Generator". Do you mean the serializer? Can you verify you are using the classic XmlSerializer or ExtendedXmlSerializer?

Additionally, it appears the code you are using didn't make it all through and I had to edit your code sample. Please ensure all code is available and I can further assist.

Finally, I do see that you are making use of classic XmlSerializer properties. While some properties are supported, some are not. One of which would be the XmlArrayItem attribute, which after a quick search of the codebase there are no supporting components. You can see more here for more context of classic serialization support:

https://github.com/ExtendedXmlSerializer/home/wiki/FAQs#systemxmlserializer-vs-extendedxmlserializer

The general recommendation is that if you are using XML that has trouble with ExtendedXmlSerializer, the best recourse is to run it through XSLT and produce an XML document that ExtendedXmlSerializer understands. From there, you can then load the document in ExtendedXmlSerializer and continue with further processing.

Please let me know the answer to the above questions and/or any further questions you have and I will do my best to assist you. 👍

GitHub
A configurable and eXtensible Xml serializer for .NET. - ExtendedXmlSerializer/home

Hi @Mike-E-angelo. I am using the ExtendedXmlSerializer. I mean the with Xml Generator the ExtendedXmlSerializer. This is the class code what I have for generating Xml. The Xml I sended, did I make by hand, that's what I need to have but dont know how to get the good Classes structure to get this output.

OK @aGreefa thank you for the further and additional context. If you are able to provide some sample XML along with a failing test/code sample of what you are experiencing I can take a look into it for you.

Thanks for helping. I created the failing test code for this.
This is the Main program:

public class Program
  {
    static void Main(string[] args)
    {
      GenerateOutput();
    }

    static List<Section> fSections =
      new List<Section>
      {
        new Section("Static")
        {
          Members = new List<Member>
          {
            new Member("Section0", "Struct")
            {
              SubMember = new List<object>()
              {
                new Member("ACR_5603", "\"UDT_ACR_Settings\""),
                new Member("ACR_5604", "\"UDT_ACR_Settings\""),
                new Member("BUC_0001_0016", "Array[1..16] of \"UDT_BUC_Settings\"")
                {
                  SubMember = new List<object>()
                  {
                    new Section("None")
                    {
                      Members = new List<Member>
                      {
                        new Member("CanalFull", "\"UDT_DEV_DIG_INPUT_Settings\"")
                        {
                          SubMember = new List<object>
                          {
                            new List<Section>
                            {
                              new Section("None")
                              {
                                Members = new List<Member>
                                {
                                  new Member("SettOnDelay", "Time")
                                  {
                                    SubMember = new List<object>
                                    {
                                      new Subelement
                                      {
                                        Path = 1, StartValue = "T#OMS"
                                      },
                                      new Subelement
                                      {
                                        Path = 2, StartValue = "T#OMS"
                                      }
                                    }
                                  }
                                }
                              }
                            }
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
      };

    public static XDocument GenerateXml<T>(T aModel)
    {
      ConfigurationContainer lConfiguration = new ConfigurationContainer();
      
      var lSerializer = lConfiguration
        .Type<List<object>>(aTypeConfiguration => aTypeConfiguration.Ignore(typeof(List<object>).GetProperty(nameof(List<object>.Capacity))))
        .Create();

      XDocument lXDocument = XDocument.Parse(lSerializer.Serialize(aModel));

      return lXDocument;
    }

    public static void GenerateOutput()
    {
      XDocument lOutputDocument = GenerateXml(fSections);

      using (XmlWriter lXmlWriterDB = XmlWriter.Create(File.Create("Test_Subelement.xml"),
        new XmlWriterSettings {Indent = true, IndentChars = "\t", OmitXmlDeclaration = true, CloseOutput = true}))
      {
        lOutputDocument.Save(lXmlWriterDB);
      }
    }
  }

This are all the classes for the Xml:

public class Section
  {
    public Section()
    {
    }

    public Section(string aName)
    {
      Name = aName;
    }

    [XmlAttribute] public string Name { get; set; }

    [XmlElement("Member")]
    public List<Member> Members { get; set; }
  }
public class Member
  {
    public Member()
    {
    }

    public Member(string aName, string aDatatype)
    {
      Name = aName;
      Datatype = aDatatype;
    }

    [XmlAttribute] public string Name { get; set; }

    [XmlAttribute]
    public string Datatype { get; set; }

    [XmlElement("Sections", typeof(List<Section>))]
    [XmlElement("Member", typeof(Member))]
    [XmlElement("Subelement", typeof(Subelement))]
    public List<object> SubMember { get; set; }
  }
 public class Subelement
  {
    [XmlAttribute]
    public int Path { get; set; }

    [XmlElement]
    public string StartValue { get; set; }
  }

This is the output Xml from this code:
image

The Xml what I want to have:
image

OK great, thank you for all that information @aGreefa, and for taking the time to compile it. I see now what you mean by Xml generator. I thought that you might have been doing some legacy XSD/XML generation based on the attributes and wanted to be sure.

Now as far as your desired output, I am afraid we are running into a few known issues with ExtendedXmlSerializer here, particularly when it involves classic XML serialization.

My recommendation for this scenario is to use XSLT on the document created by ExtendedXmlSerializer. You should be able to format the document exactly as desired via XSLT, and then send that resulting document onto the next consumer in your scenario.

I know that isn't ideal, and will involve some more work for you, but that's the best option I can recommend. There are some configurations we can apply to the ConfigurationContainer, but at the end of the day, we're running into a few issues in how ExtendedXmlSerializer creates the output, particularly with properties that are list elements.

There is also the issue with the exs:member="true" which is a hacky way that is currently implemented to discern between member properties that have the same names as types in the same namespace. This is easily removed via XSLT if needed.

Sorry that I am not able to provide a helpful answer here. If you do have any further questions/comments please do let me know and I will see if I can assist you further.

Going through the issues here, and this appears to be addressed as much as we address it. It has been added as a known issue for others to view when reading the README. Please do let me know if you have any additional questions/issues and I will do my best to assist. Closing for now.