views:

868

answers:

2

Problem

I'm using Xsd2Code (a .NET class generator for XSD schema) on a simple settings file schema. For some reason, when I attempt to use the built-in LoadFromFile() or Deserialize() methods, I get an exception that seems to be related to the xmlns attributes in my XSD and XML files. If I remove these attributes, the exception goes away. (Please see my "Update" below for details on the code that is actually causing the exception.)


XSD File

<?xml version="1.0" encoding="utf-8"?>
<xs:schema
  xmlns="Myco.CLDatabaseBuilder.Models"
  xmlns:xs="http://www.w3.org/2001/XMLSchema"
  targetNamespace="Myco.CLDatabaseBuilder.Models"
  elementFormDefault="qualified">
  <xs:element name="Settings" type="Settings" />
  <xs:complexType name="Settings">
    <xs:sequence>
      <xs:element name="SqlServerInstanceName" type="xs:string" />
      <xs:element name="DatabaseName" type="xs:string" />
      <xs:element name="RootDatabaseName" type="xs:string" />
    </xs:sequence>
  </xs:complexType>
</xs:schema>

XML File (fails) - I get an Exception when I attempt to deserialize

<?xml version="1.0" encoding="UTF-8"?>
<Settings
  xmlns="Myco.CLDatabaseBuilder.Models"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="Myco.CLDatabaseBuilder.Models Settings.xsd">
  <SqlServerInstanceName>SQLEXPRESS</SqlServerInstanceName>
  <DatabaseName>CL</DatabaseName>
  <RootDatabaseName>master</RootDatabaseName>
</Settings>

XML File (succeeds) - deserialization works fine

<?xml version="1.0" encoding="UTF-8"?>
<Settings
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="Myco.CLDatabaseBuilder.Models Settings.xsd">
  <SqlServerInstanceName>SQLEXPRESS</SqlServerInstanceName>
  <DatabaseName>CL</DatabaseName>
  <RootDatabaseName>master</RootDatabaseName>
</Settings>

Exception Details - what happens if I run the "failure example"

A first chance exception of type 'System.InvalidOperationException' occurred in System.Xml.dll
System.InvalidOperationException: There is an error in XML document (2, 2). ---> System.InvalidOperationException: <Settings xmlns='Myco.CLDatabaseBuilder.Models'> was not expected.
   at Microsoft.Xml.Serialization.GeneratedAssembly.XmlSerializationReaderSettings.Read3_Settings()
   --- End of inner exception stack trace ---
   at System.Xml.Serialization.XmlSerializer.Deserialize(XmlReader xmlReader, String encodingStyle, XmlDeserializationEvents events)
   at System.Xml.Serialization.XmlSerializer.Deserialize(XmlReader xmlReader)
   at Myco.CLDatabaseBuilder.Models.Settings.Deserialize(String xml) in C:\...\CLDatabaseBuilder\Models\Settings.cs:line 118
   at Myco.CLDatabaseBuilder.Models.Settings.LoadFromFile(String fileName) in C:\...\CLDatabaseBuilder\Models\Settings.cs:line 195
   at Myco.CLDatabaseBuilder.Program.InitializeSettings() in C:\...\CLDatabaseBuilder\Program.cs:line 68

Questions:

So basically, I have to strip out the default namespace to be able to deserialize.

Any idea why I'm getting an exception when I use xmlns? This namespace declaration is very helpful for doing live validation in Visual Studio, so I'd like to keep it if possible.

Is something wrong with my XSD root element attributes? I've messed with elementFormDefault (changing from qualified to unqualified), but this didn't solve the problem.


Update

The code it's actually choking on is this:

Serializer = new System.Xml.Serialization.XmlSerializer(typeof(Myco.CDDatabaseBuilder.Models.Settings));
Serializer.Deserialize(System.Xml.XmlReader.Create(stringReader));

As shown in the exception above, the error I'm getting is:

<Settings xmlns='Myco.CLDatabaseBuilder.Models'> was not expected.

Does this suggest anything to look for in my Settings class (the class generated by Xsd2Code)? There are [System.Xml.Serialization...] attributes sprinkled throughout this class. I wonder if something is missing, or if the class (or the serializer) doesn't have a way of modeling the default xmlns attribute. Any ideas appreciated.

A: 

One of those days...turns out I needed four little characters.

There's a switch in Xsd2Code /xa+ that sets GenerateXMLAttributes = true

For some reason, the default for this is false. Well, it needs to be true if you have an xmlns attribute and you want to deserialize.

DanM
+1  A: 

I don't know what the problem is, but it should work. You're right to be confused. I ran your schema through the xsd.exe tool that is shipped with the .NET SDK. It generates this class from your schema:

[XmlType(Namespace="Myco.CLDatabaseBuilder.Models")]
[XmlRoot(Namespace="Myco.CLDatabaseBuilder.Models", IsNullable=false)]
public partial class Settings {

    private string sqlServerInstanceNameField;

    private string databaseNameField;

    private string rootDatabaseNameField;

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

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

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

As you can see there are few attributes decorating the class. There's an XmlType and an XmlRoot, and that's it. The three properties in that class are implicitly serialized, even without the XmlElement attribute.

The result I get from re-serializing your XML is this:

<q1:Settings xmlns:q1="Myco.CLDatabaseBuilder.Models">
  <q1:SqlServerInstanceName>SQLEXPRESS</q1:SqlServerInstanceName>
  <q1:DatabaseName>CL</q1:DatabaseName>
  <q1:RootDatabaseName>master</q1:RootDatabaseName>
</q1:Settings>
Cheeso
+1 for the effort, but I actually figured out the problem (see my answer). Interesting that when you re-serialize, it does `xmlns:q1` instead of just using a default namespace.
DanM