0

I am under a situation where i tried to do serialization :

My classes are like this:

 [XmlRoot(ElementName = "ps")]
  public class Ps
  {
   [XmlElement("sep")]
   public List<Sep> Sep { get { return a1; } }
   private readonly List<Sep> a1 = new List<Sep>(); 

   [XmlElement("pr")]
   public List<Pr> Pr { get { return b1; } }
   private readonly List<Pr> b1 = new List<Pr>();
 }


 [XmlRoot(ElementName = "attr")]
public class Attr
{     
    [XmlElement("type")],
    public string Type { get; set; }

    [XmlElement("value")]
    public int Value { get; set; }

}

    [XmlRoot(ElementName = "pr")]
          public class Pr
        {
            [XmlElement("name")]
            public string Name { get; set; }

            [XmlElement("comp")]
            public List<Comp> Comp { get { return b3; } }
            private readonly List<Comp> b3 = new List<Comp>();

        }
 [XmlRoot(ElementName = "sep")]
    public class Sep
    {
        [XmlElement("sep")]
        public string Sep { get; set; }

    }

 public void Main()
{

            Ps pc = new Ps()
              {
                Pr = { new Pr { Name = "Name1",  Component = { new Comp { Type = "CB", Attr = { new Attr { Value = "0" } } } } }, { new Pr { Name = "Name2" ,Comp = { new Comp { Type = "RB", Attr = { new Attr { Value = "l" ....And so On} } } } } } }
             ,
                Sep = { new Sep { Sep = "sep1" ..and so on} }  

              };
            var xml = pc.ToXml(); 
}

The xml obtained is supposed to be like this :

<ps>
    <pr>
        <name>name1</name>
        <comp>
            <type>CB</type>
            <attr>
                <value>0</value>
            </attr>
        </comp>
    </pr>
    <sep>sep1</sep>
    <pr>
        <name>name2</name>
        <comp>
            <type>RB</type>
            <attr>
                <value>1</value>
            </attr>
        </comp>
    </pr>
    <sep>sep2</sep>
    <pr>
        <name>name3</name>
        <comp>
            <type>CoM</type>
            <attr>
                <value>2</value>
            </attr>
        </comp>
    </pr>
    <sep>sep3</sep>
</ps>

But unfortunately it is like this:

<ps>
  <sep>sep1</sep>
  <sep>sep2</sep>
  <sep>sep3</sep>
  <pr>
      <name>name1</name>
       <comp>
            <type>CB</type>
            <attr>
                <value>0</value>
            </attr>
       </comp>
    </pr>    
    <pr>
        <name>name2</name>
        <comp>
            <type>RB</type>
            <attr>
                <value>1</value>
            </attr>
        </comp>
    </pr>    
    <pr>
        <name>name3</name>
        <comp>
            <type>CoM</type>
            <attr>
                <value>2</value>
            </attr>
        </comp>
    </pr>  
</ps>

The xml contains all "sep" together and all "pr" together. How to maintain the sequence of "pr" and "sep" as it is supposed to be obtained ? I tried using XElemnt but the problem is we do everythign statically there,Like this:

var el =   new XElement("ps",
                       new XElement("pr",
                           new XElement("name", "name1"),
                           new XElement("comp",
                               new XElement("type", "CB"),
                               new XElement("attr",
                                   new XElement("value", 0)
                               )
                           )
                       ),//And so on..

I also tried something like this :

 Ps pc = new Ps()
              {
                Pr = { new Pr { Name = "Name1",  Comp = { new Comp { Type = "Type1", Attr = { new Attr { Type = "Com" } } } } }, { new Pr { Name = "Name2" ,Comp = { new Comp { Type = "Type2", Attr = { new Attr { Type = "Sl" ....And so On} } } } } } }
             ,
                Sep = { new Sep { Sep = "sep1" ..and so on} }  
              , Pr = { new Pr { Name = "Name1",  Component //so on 
              ,Sep = { new Sep { Sep = "sep1" ..and so on} }  
              };
        var xml = pc.ToXml(); 

which will ofcourse not work duplicate intialisation of Pr ans sep.

We assign here like this XElement("name", "name1") but i want something like this ps Object1 = new ps(); and Object1.pr[0].Name= "name1"; How to achieve this ?

EDIT: I tried te code" below after Austinh's comments:

public void Main()
{
   List<object> lst = new List<object>();
   Ps pc = new Ps()
   {
          Pr = { new Pr { Name = "Name1",Comp = { new Comp { Type = "Type1", Attr = { new Attr { Type = "Combo"} } } } }}
     ,
          Sep = { new Sep{ Sep = "AutoSkew1" } }
    };

   Ps pc1 = new Ps()
   {
       Pr = { new Pr { Name = "Name3", Comp = { new Comp { Type = "Type3", Attr = { new Attr { Type = "Rb"} } } } } }
   ,
       Sep = { new Sep { Sep = "AutoSkew2" }}
   };
   lst.Add(pc);
   lst.Add(pc1);
   var xml = lst.ToXml();
}

But i have invalid excceptionhandled by user :There was an error generating the XML document.In the line serializer.Serialize(writer, objectToSerialize); in the code below:

public static string ToXml(this object objectToSerialize)
        {
            var writer = new StringWriter();
            var serializer = new XmlSerializer((objectToSerialize.GetType()));
            serializer.Serialize(writer, objectToSerialize);
            string xml = writer.ToString();
            return xml;
        }
Sss
  • 1,519
  • 8
  • 37
  • 67
  • I don't think it's possible to do that with the built-in `XmlSerializer` short of implementing the [`IXmlSerializable` interface](http://msdn.microsoft.com/en-us/library/system.xml.serialization.ixmlserializable.aspx). – Chris Sinclair Jun 24 '14 at 14:11
  • @ChrisSinclair I am stuck here since a week . Could you please help me in telling any alternative to achieve this? I really need help . – Sss Jun 24 '14 at 14:12
  • Try making Ps contain a List (will maintain the order and generic) of your pr and sep objects. [And stop reposting this question](http://stackoverflow.com/questions/24383991/how-to-use-xelement-in-this-situation). This is the 3rd repost i know of. – Austinh100 Jun 24 '14 at 14:28
  • @Austinh100 Thanks but "Try making Ps contain a List " . i couldn't understand How ? (could you please explain in more detail with little explained code). I repeated it because until i am not able to getthe satisfactory answer to do it. – Sss Jun 24 '14 at 14:30
  • Infact everybody say that it is not possible using "XmlSerializer" but how to do? No body explains. – Sss Jun 24 '14 at 14:45
  • @user234839: You can attempt to implement the `IXmlSerializable` interface and failing that you can post _that_ attempt as a new question asking a specific question about how to work with the `XmlWriter` object. I think there is no "built-in" way to match that XML schema you want; you're gonna have to bite the bullet and construct the elements manually. You could definitely continue what you're doing with the `XElement` construction, likely with some looping for each `Pr` element. Just move the code into some utility to convert to/from your `Ps` objects arbitrarily. – Chris Sinclair Jun 24 '14 at 15:30
  • @ChrisSinclair Ok it would be complicated but do you think that what Austinh100 is trying to explain is possible ? And you please explaine bit more if it can be achieved ? – Sss Jun 24 '14 at 15:57

1 Answers1

1

I have not tested this so it may not work but here is a possible way to have a structure like that.

Adapted from: c# serialize nested class

public class Ps
{
    [XmlArray("ps")]
    public List<object> items { get { return a1; } }
    private readonly List<object> a1 = new List<object>(); 
}

And then add (sep or pr) to the Ps list when needed which will keep the order that it was added to.

Expanding on your main edit (implying implementation of above code):

public void Main()
{
   Ps pc = new Ps();
   pc.items.Add(new Pr { Name = "Name1",Comp = { new Comp { Type = "Type1", Attr = { new Attr { Type = "Combo"} } } } });
   pc.items.Add(new Sep{ Sep = "AutoSkew1" });

   pc.items.Add(new Pr { Name = "Name3", Comp = { new Comp { Type = "Type3", Attr = { new Attr { Type = "Rb"} } } } });
   pc.items.Add(new Sep { Sep = "AutoSkew2" });
   var xml = pc.items.ToXml();
}
Community
  • 1
  • 1
Austinh100
  • 598
  • 3
  • 13
  • thanks for answer but i forgot to include in my code this ps class. see the edit please. – Sss Jun 24 '14 at 14:43
  • still we will need two List for "pr" and "sep". so it will not work i guess. Am i right ? – Sss Jun 24 '14 at 14:44
  • Still it will not work i guess. Where are "pr" and "sep" . Do i need to make one more list for them each? – Sss Jun 24 '14 at 15:01
  • You add to the generic object list your pr and sep objects as needed. All C# objects inherit from object so they will be allowed to be added to the list. – Austinh100 Jun 24 '14 at 15:02
  • but they are also suposed to be list (because there are many ps and sep and i want List instead of array). Why you have made ps as array [XmlArray("ps")] whereas there is only one ps. Could you please explain me all because your code double confused me. – Sss Jun 24 '14 at 15:05
  • could you please explain the doubt i had asked last time so that i will try to understand it and mark you as answer. – Sss Jun 25 '14 at 07:13
  • i tried to what you suggested but it gives exception.PLEASE SEE THE ADDED CODE IN MY QUESTION. – Sss Jun 25 '14 at 08:14
  • @user234839 see edit. Ps in this case would be the list object (which is why it is considered an xmlarray), so you would just use it as one. – Austinh100 Jun 25 '14 at 12:49
  • But Ps is root.[XmlRoot(ElementName = "ps")] Can i replace root with the [XmlArray("ps")] ? – Sss Jun 25 '14 at 12:51
  • And plealso see the part below EDIT: I tried to implement the thing like this And i got error. – Sss Jun 25 '14 at 12:53
  • Yes if you implement `[XmlArray("ps")] public List Ps` as explicitly shown in the answer... – Austinh100 Jun 25 '14 at 12:54
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/56270/discussion-between-user234839-and-austinh100). – Sss Jun 25 '14 at 12:58
  • please come in chat room. – Sss Jun 25 '14 at 12:58