-1

Framework is c# .net 4.6.2

I am generating automatic XML classes from XML codes

When I auto generate, it automatically converts as Array[][]

But i want to use it as List<List<>>

And i am sure that my conversation from Array to List causes some serialization error. I think it is about get and set functions. So i need your help to fix this issue

Here the auto generated code piece when i edit > paste special > paste XML as classes

    /// <remarks/>
[System.SerializableAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)]
public partial class OxFordDefinition_perGroup
{

    private string _GroupDescField;

    private string _GroupSenseField;

    private string _GroupGrammerField;

    private OxFordDefinition_perGroup_perMainExample_perSubExample[][] _perMainExampleField;

    /// <remarks/>
    public string _GroupDesc
    {
        get
        {
            return this._GroupDescField;
        }
        set
        {
            this._GroupDescField = value;
        }
    }

    /// <remarks/>
    public string _GroupSense
    {
        get
        {
            return this._GroupSenseField;
        }
        set
        {
            this._GroupSenseField = value;
        }
    }

    /// <remarks/>
    public string _GroupGrammer
    {
        get
        {
            return this._GroupGrammerField;
        }
        set
        {
            this._GroupGrammerField = value;
        }
    }

    /// <remarks/>
    [System.Xml.Serialization.XmlArrayItemAttribute("_perSubExample", typeof(OxFordDefinition_perGroup_perMainExample_perSubExample), IsNullable = false)]
    public OxFordDefinition_perGroup_perMainExample_perSubExample[][] _perMainExample
    {
        get
        {
            return this._perMainExampleField;
        }
        set
        {
            this._perMainExampleField = value;
        }
    }
}

But instead of arrays, i want to use List<List<>>

So i make it like below

        /// <remarks/>
    [System.SerializableAttribute()]
    [System.ComponentModel.DesignerCategoryAttribute("code")]
    [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)]
    public partial class OxFordDefinition_perGroup
    {

        private string _GroupDescField;

        private string _GroupSenseField;

        private string _GroupGrammerField;

        private  List<List<OxFordDefinition_perGroup_perMainExample_perSubExample>> _perMainExampleField;

        /// <remarks/>
        public string _GroupDesc
        {
            get
            {
                return this._GroupDescField;
            }
            set
            {
                this._GroupDescField = value;
            }
        }

        /// <remarks/>
        public string _GroupSense
        {
            get
            {
                return this._GroupSenseField;
            }
            set
            {
                this._GroupSenseField = value;
            }
        }

        /// <remarks/>
        public string _GroupGrammer
        {
            get
            {
                return this._GroupGrammerField;
            }
            set
            {
                this._GroupGrammerField = value;
            }
        }

        /// <remarks/>
        [System.Xml.Serialization.XmlArrayItemAttribute("_perSubExample", typeof(OxFordDefinition_perGroup_perMainExample_perSubExample), IsNullable = false)]
        public List<List<OxFordDefinition_perGroup_perMainExample_perSubExample>> _perMainExample
        {
            get
            {
                return this._perMainExampleField;
            }
            set
            {
                this._perMainExampleField = value;
            }
        }
    }

But this time it gives serialization error when i try to serialize like below

       public static string SerializeXML<T>(this T toSerialize)
    {
        XmlSerializer xmlSerializer = new XmlSerializer(typeof(T));
        StringWriter textWriter = new StringWriter();
        xmlSerializer.Serialize(textWriter, toSerialize);
        return textWriter.ToString();
    }

Here the full code of the XML class

http://pastebin.com/y5B8ENM3

Here the error it gives

enter image description here

dbc
  • 104,963
  • 20
  • 228
  • 340
Furkan Gözükara
  • 22,964
  • 77
  • 205
  • 342

1 Answers1

3

Actually neither your original nor your modified OxFordDefinition_perGroup can be serialized successfully. The problem is your value for XmlArrayItem.Type, which is the second argument to the constructor:

[System.Xml.Serialization.XmlArrayItemAttribute("_perSubExample", typeof(OxFordDefinition_perGroup_perMainExample_perSubExample), IsNullable = false)]
public OxFordDefinition_perGroup_perMainExample_perSubExample[][] { get; set; }

According to the docs

Use the Type property to specify an overridden type for a public field or public read/write property value.

If a field or property returns an array of type Object, apply multiple instances of the XmlArrayItemAttribute to the field or property. For each instance, set the Type property to a type of object that can be inserted into the array.

The typeof(OxFordDefinition_perGroup_perMainExample_perSubExample) indicates that items in the outermost collection will be of type typeof(OxFordDefinition_perGroup_perMainExample_perSubExample). However, in fact the items in the array or list are of type OxFordDefinition_perGroup_perMainExample_perSubExample[] or List<OxFordDefinition_perGroup_perMainExample_perSubExample> respectively, which cannot, of course, be assigned to this type. This XmlSerializer code generation fails.

If you remove the type setting entirely from your [XmlArrayItem] attribute then both versions of your type will be serializable to XML:

[System.Xml.Serialization.XmlArrayItemAttribute("_perSubExample", IsNullable = false)]
public List<List<OxFordDefinition_perGroup_perMainExample_perSubExample>> _perMainExample
{
    get
    {
        return this._perMainExampleField;
    }
    set
    {
        this._perMainExampleField = value;
    }
}

Sample fiddle.

Update

You asked, it adds extra layer which should not exists. any idea?

This is because you are using nested lists or jagged arrays. Change it to be a simple list or 1-d array:

private List<OxFordDefinition_perGroup_perMainExample_perSubExample> _perMainExampleField;

/// <remarks/>
[System.Xml.Serialization.XmlArrayItemAttribute("_perSubExample", IsNullable = false)]
public List<OxFordDefinition_perGroup_perMainExample_perSubExample> _perMainExample
{
    get
    {
        return this._perMainExampleField;
    }
    set
    {
        this._perMainExampleField = value;
    }
}

Sample fiddle #2.

I then downloaded the entire XML from http://pastebin.com/raw/BJhRfFNf and ran xsd.exe to generate a schema, and then classes, from the XML, and I was able to reproduce your problem - incorrect classes were generated. I then manually changed the jagged array to a flat array (a List<T> would work fine also) and was able to serialize and deserialize the XML without an exception getting thrown:

Sample fiddle #3.

Unfortunately, it appears that only the first </_perMainExample> node is successfully deserialized using these tweaked classes, so at this point this auto-generated code just doesn't seem viable.

I'm not sure why xsd.exe generated bad code here, you might want to ask another question or open an issue with Microsoft.

Final Update

It looks as though xsd.exe (and thus Paste XML as Classes) is having trouble with a repeating element that contains nested repeating elements:

<_perMainExample>
  <_perSubExample>
  </_perSubExample>

  <_perSubExample>
  </_perSubExample>
</_perMainExample>

<_perMainExample>
  <_perSubExample>
  </_perSubExample>

  <_perSubExample>
  </_perSubExample>
</_perMainExample>

I'm not sure what the problem is, but at this point I recommend switching to a different code-generation tool such as https://xmltocsharp.azurewebsites.net/, which generates the following classes:

[XmlRoot(ElementName="_Example")]
public class _Example {
    [XmlElement(ElementName="_SenseNot")]
    public string _SenseNot { get; set; }
    [XmlElement(ElementName="_GrammaticNot")]
    public string _GrammaticNot { get; set; }
    [XmlElement(ElementName="_Desc")]
    public string _Desc { get; set; }
}

[XmlRoot(ElementName="_perSubExample")]
public class _perSubExample {
    [XmlElement(ElementName="_UpperTitle")]
    public string _UpperTitle { get; set; }
    [XmlElement(ElementName="_FormGroup")]
    public string _FormGroup { get; set; }
    [XmlElement(ElementName="_SenseNot")]
    public string _SenseNot { get; set; }
    [XmlElement(ElementName="_GrammaticNot")]
    public string _GrammaticNot { get; set; }
    [XmlElement(ElementName="_Desc")]
    public string _Desc { get; set; }
    [XmlElement(ElementName="_Example")]
    public List<_Example> _Example { get; set; }
    [XmlElement(ElementName="_Synonyms")]
    public string _Synonyms { get; set; }
}

[XmlRoot(ElementName="_perMainExample")]
public class _perMainExample {
    [XmlElement(ElementName="_perSubExample")]
    public List<_perSubExample> _perSubExample { get; set; }
}

[XmlRoot(ElementName="_perGroup")]
public class _perGroup {
    [XmlElement(ElementName="_GroupDesc")]
    public string _GroupDesc { get; set; }
    [XmlElement(ElementName="_GroupSense")]
    public string _GroupSense { get; set; }
    [XmlElement(ElementName="_GroupGrammer")]
    public string _GroupGrammer { get; set; }
    [XmlElement(ElementName="_perMainExample")]
    public List<_perMainExample> _perMainExample { get; set; }
}

[XmlRoot(ElementName="OxFordDefinition")]
public class OxFordDefinition {
    [XmlElement(ElementName="sourceURL")]
    public string SourceURL { get; set; }
    [XmlElement(ElementName="originDesc")]
    public string OriginDesc { get; set; }
    [XmlElement(ElementName="_perGroup")]
    public List<_perGroup> _perGroup { get; set; }
}

Notice that:

  1. The code generated is much, much cleaner.

  2. An extra level of class _perMainExample is added to encapsulate the inner _perSubExample list.

Sample fiddle #4 which shows that the original and re-serialized XML are identical by calling XNode.DeepEquals().

dbc
  • 104,963
  • 20
  • 228
  • 340
  • ty very much now it works but it adds extra layer which should not exists. any idea? http://orig01.deviantart.net/97e8/f/2017/058/c/1/extalayer_by_monstermmorpg-db0kptm.png – Furkan Gözükara Feb 27 '17 at 16:43
  • here example xml code that i use to generate auto code : http://pastebin.com/BJhRfFNf – Furkan Gözükara Feb 27 '17 at 16:45
  • jagged array to flat array means [][] to []? well this is not what i want. i need to store info like here with multiple _perMainExample under each _perGroup : http://pastebin.com/BJhRfFNf – Furkan Gözükara Feb 27 '17 at 17:10
  • awesome ty very much. this site lives by the help of people like you. those 2 negative giver leechers and even selecting the close button leechers should be banned from SO forever. so in the end it was all billion dollar company microsoft's faulty code generation system – Furkan Gözükara Feb 27 '17 at 17:32
  • Thanks a mill for xmltocsharp.azurewebsites.net, it really saved my day. I've been going crazy at the hands of MS's XSD failing to generate serializable c# because of a particular bit of nested nodes in the xml. Open-source beat xsd hands down and it generated human readable output AND capitalized the attributes as a nice bonus. Thanks again! – Arman Aug 27 '19 at 15:57