Jan
Jan

Reputation: 2779

C# XmlSerializer ignores xs:attribute with types other than xs:string

my problem seems very odd and I did not find any other with that problem, so I guess it is a very simple and stupid mistake, which I can't seem to find out.

I have an XSD, from which I generate a class structure using xsd.exe. I "fill" my object with values, but when serializing it to XML it ignores all class-properties which are not of type string.

var myGraph = new graph();
myGraph.myString = "hallo";
myGraph.myInt = 80;

var serializer = new XmlSerializer(typeof(graph));
TextWriter writeFileStream = new StreamWriter(Path.Combine(outFolder, outFile));
serializer.Serialize(writeFileStream, myGraph);
writeFileStream.Close();

I expected:

<graph xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"  
    myString="hallo" 
    myInt="80"
/>

The actual output is:

<graph xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
    myString="hallo" 
/>

The attribute myInt has been ignored. If I define it as a string, it will also appear, but as any other type it will not show up. If I declare it required and leave it null, it will be serialized as myInt="0".

What am I missing?

Some details:

XSD:

<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
  <xs:element name="graph">
    <xs:complexType>
      <xs:attribute name="myString" type="xs:string" />
      <xs:attribute name="myInt" type="xs:int" />
    </xs:complexType>
  </xs:element>
</xs:schema>

generated class:

[System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "2.0.50727.3038")]
[System.SerializableAttribute()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType=false)]
[System.Xml.Serialization.XmlRootAttribute(Namespace="", IsNullable=false)]
public partial class graph {
    private string myStringField;
    private int myIntField;

    [System.Xml.Serialization.XmlAttributeAttribute(Form=System.Xml.Schema.XmlSchemaForm.Qualified)]
    public string myString {
        get { return this.myStringField; }
        set { this.myStringField = value; }
    }

    [System.Xml.Serialization.XmlAttributeAttribute(Form=System.Xml.Schema.XmlSchemaForm.Qualified)]
    public int myInt {
        get { return this.myIntField; }
        set { this.myIntField = value; }
    }

    [System.Xml.Serialization.XmlIgnoreAttribute()]
    public bool myIntSpecified {
        get { return this.myIntFieldSpecified; }
        set { this.myIntFieldSpecified = value; }
    }

Upvotes: 1

Views: 2541

Answers (3)

Aliostad
Aliostad

Reputation: 81700

There something else going on your side my friend. I did compile the code and it worked perfectly:

class:

[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = false)]
[System.Xml.Serialization.XmlRootAttribute(Namespace = "", IsNullable = false)]
public partial class graph
{
    private string myStringField;
    private int myIntField;

    [System.Xml.Serialization.XmlAttributeAttribute(Form = System.Xml.Schema.XmlSchemaForm.Qualified)]
    public string myString
    {
        get { return this.myStringField; }
        set { this.myStringField = value; }
    }

    [System.Xml.Serialization.XmlAttributeAttribute(Form = System.Xml.Schema.XmlSchemaForm.Qualified)]
    public int myInt
    {
        get { return this.myIntField; }
        set { this.myIntField = value; }
    }


}

Code:

    graph g = new graph() {myInt = 80, myString = "ali"};
    XmlSerializer xss = new XmlSerializer(typeof (graph));
    MemoryStream ms = new MemoryStream();
    xss.Serialize(ms, g);
    StreamReader sb = new StreamReader(ms);
    ms.Position = 0;
    Console.WriteLine(sb.ReadToEnd());

Output:

<graph xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org
/2001/XMLSchema-instance" myString="ali" myInt="80" />

Upvotes: 0

pmartin
pmartin

Reputation: 2741

XSD will add an additional "specified" field for all properties that are value types. When using .NET serialization with value types, you will always need to specify the field's value and set the matching "specified" property to true.

Change you code to this and it will work as expected:

var myGraph = new graph();
myGraph.myString = "hallo";
myGraph.myInt = 80;
myGraph.myIntSpecified = true;

Upvotes: 7

Steven Jeuris
Steven Jeuris

Reputation: 19130

I'm not 100% sure about this, but remember something similar. See the generated 'myIntSpecified' field? You should set this to true.

xsd.exe has some big limitations, you could google for alternatives, or simply remember setting it to true every time. :)

Upvotes: 2

Related Questions