Himberjack
Himberjack

Reputation: 5802

StackOverflowException when de-serializing XSD

I have the following schema, which is has Category recursive. I tried using Xsd2Code in order to generate Class for this schema. When I try to deserialize it, I am getting StackOverFlow exception.

In the construction of the class there is:

public category()
        {
            this.catField = new category();
            this.channelField = new List<categoryChannel>();
        }

that's why I guess it is going SO.

What am I doing wrong??? thanks!

<?xml version="1.0" encoding="utf-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified">
    <xs:complexType name="category">
        <xs:sequence>
            <xs:element name="channel" minOccurs="0" maxOccurs="unbounded">
                <xs:complexType>
                    <xs:attribute name="id" type="xs:int"/>
                </xs:complexType>
            </xs:element>
            <xs:element name="cat" type="category" minOccurs="0"/>
        </xs:sequence>          
    </xs:complexType>
    <xs:element name="MH_CategoriesTree">
        <xs:complexType>
            <xs:sequence>
                <xs:element name="response">
                    <xs:complexType>
                        <xs:sequence>
                            <xs:element name="cat" type="category"/>
                        </xs:sequence>
                        <xs:attribute name="type"/>
                    </xs:complexType>
                </xs:element>
            </xs:sequence>
        </xs:complexType>
    </xs:element>
</xs:schema>

the error

An unhandled exception of type 'System.StackOverflowException' occurred in  XXX.dll

Upvotes: 0

Views: 533

Answers (2)

Marc Gravell
Marc Gravell

Reputation: 1064044

Basically, xsd2code is doing it wrong (see MizardX's answer for why, in the constructor).

As a repro, I used:

xsd foo.xsd /classes

to generate classes (rather than xsd2code), then the following basic example works absolutely fine:

using System;
using System.IO;
using System.Xml.Serialization;
static class Program
{
    static void Main()
    {
        MH_CategoriesTree root = new MH_CategoriesTree(), clone;
        root.response = new MH_CategoriesTreeResponse();
        root.response.type = "alpha";
        root.response.cat = new category
        {
            cat = new category
            {
                cat = new category
                {
                    channel = new categoryChannel[]
                    {
                       new categoryChannel { id = 123, idSpecified = true }
                    }
                },
                channel = new categoryChannel [0]
            },
            channel = new categoryChannel[]
            {
                new categoryChannel { id = 456, idSpecified = true},
                new categoryChannel { id = 789, idSpecified = true },
            }
        };

        var ser = new XmlSerializer(typeof(MH_CategoriesTree));
        string xml;
        using(var sw = new StringWriter())
        {
            ser.Serialize(sw, root);
            xml = sw.ToString();
        }
        using(var sr = new StringReader(xml))
        {
            clone = (MH_CategoriesTree) ser.Deserialize(sr);
        }
        // now write "clone" to Console, to show it all worked
        ser.Serialize(Console.Out, clone);
    }
}

So options:

  • use xsd.exe, not xsd2code
  • submit a bug report for xsd2code
  • perhaps manually fix the xsd2code-generated constructor, such that it doesn't create the child category

Another possible cause of recursion here is simply: to make your model recursive! for example:

    MH_CategoriesTree root = new MH_CategoriesTree(), clone;
    root.response = new MH_CategoriesTreeResponse();
    root.response.type = "alpha";
    var cat = new category();
    cat.cat = cat;
    root.response.cat = cat; // now we have an infinite loop

which will, with the rest of the code as-above, cause it to explode in a shower of sparks:

A circular reference was detected while serializing an object of type category.

However, a recursive schema itself works just fine.

Upvotes: 1

Markus Jarderot
Markus Jarderot

Reputation: 89231

If that code snippet is a constructor, you have direct recursion. The first line creates an object of the same type, which calls the same constructor.

Upvotes: 3

Related Questions