Linq To Xsd not respecting xs:sequence field order

Apr 26, 2011 at 3:04 PM

Hi,

Not sure what's going on here. For this type:

	<xs:complexType name="Method">
		<xs:sequence>
			<xs:element name="Name" type="xs:string"/>
			<xs:element name="Type" type="xs:string"/>
			<xs:element name="AccessModifier" type="xs:string"/>
			<xs:element name="Class" type="xs:string"/>
			<xs:element name="ClassType" type="xs:string"/>
			<xs:element name="Filename" type="xs:string"/>
			<xs:element name="Index" type="xs:int"/>
			<xs:element name="Length" type="xs:int"/>
			<xs:sequence minOccurs="0" maxOccurs="unbounded">
				<xs:element name="ChildMethods" type="xs:string"/>
			</xs:sequence>
		</xs:sequence>
	</xs:complexType>

And this code:

                    candidateMethod = new Method()
                    {
                        Filename = file,
                        Index = m.Index,
                        Length = m.Length,
                        Name = m.Groups["Name"].Value,
                        Class = Path.GetFileName(file),
                        ClassType = sClassType,
                        Type = m.Groups["Type"].Value,
                        AccessModifier = m.Groups["AccessModifer"].Value
                    };

                    codeStructure.Methods.Add(candidateMethod);

I'm getting this Xml:

	<Methods>
		<Filename>House\Background\bas\msl_BCK_BackgroundLookups.bas</Filename>
		<Index>2520</Index>
		<Length>611</Length>
		<Name>fn_Lookup_ConfigScheduleEnabledFromID</Name>
		<Class>msl_BCK_BackgroundLookups.bas</Class>
		<ClassType/>
		<Type>Function</Type>
		<AccessModifier>Public</AccessModifier>
		<ChildMethods>fn_Create_WHERE</ChildMethods>
		<ChildMethods>fn_Boolean</ChildMethods>
		<ChildMethods>fn_Lookup</ChildMethods>
	</Methods>

(ignore the ChildMethods, that gets populated later in the code)

That Xml does not conform to the schema, the fields are in the order they were written in the code, not the order of the xs:sequence fields

I assumed that Linq to Xsd would write out Xml that conformed to the schema but it appears this is not so?

Have I overestimated the functionality or have I done something wrong?

Or is this a bug?

 

Regards,

James.

Apr 27, 2011 at 8:14 AM

Looks like a bug to me. I don't see a technical reason why this couldn't be able to be achieved.

Apr 27, 2011 at 8:47 PM
Edited Apr 27, 2011 at 10:25 PM
I discovered the same problem yesterday as well.  I can think of two ways to potentially resolve this:
  1. Override the ToString() method on the class(es) for which you want to control the serialization order (e.g. the Method class in your example above).  Not ideal, but it might get you past a roadblock.
  2. Create a subclass and implement a new ContentModelEntity IXMetaData.GetContentModel() method that returns a (static scoped) instance of  SequenceContentModelEntity (in the source code for the LinqToXsd project, it looks like the schema-aware logic is there.  See the ContentModel.cs file in the source). 

 So, in your example above, you might try something like:

public class SequenceMethod : Method, IXMetaData
{
    private static readonly SequenceContentModelEntity contentModel =
        new SequenceContentModelEntity(
            new NamedContentModelEntity(XName.Get("Name", "http://tempuri.org")),
            new NamedContentModelEntity(XName.Get("Type", "http://tempuri.org")),
            new NamedContentModelEntity(XName.Get("AccessModifier", "http://tempuri.org")),
            new NamedContentModelEntity(XName.Get("Class", "http://tempuri.org")),
            new NamedContentModelEntity(XName.Get("ClassType", "http://tempuri.org")),
            new NamedContentModelEntity(XName.Get("Filename", "http://tempuri.org")),
            new NamedContentModelEntity(XName.Get("Index", "http://tempuri.org")),
            new NamedContentModelEntity(XName.Get("Length", "http://tempuri.org"))
            );

    ContentModelEntity IXMetaData.GetContentModel()
    {
        return contentModel;
    }
}

Hope this helps.