简体   繁体   中英

data-loss from using auto-generated serializer

I have an xsd file that describes a small schema. I created a C# file with the help of xsd.exe (I ran this command in the developer command prompt: xsd.exe smallSchema.xsd /classes /language:CS ) to be able to easily (de-)serialize it. I took an xml file that complies to that schema and tried to deserialize it by using the generated code. But i noticed that data loss occurs!

Can anyone point me to the cause of that data loss?

This is the xml file that I want to deserialize:

<?xml version="1.0" encoding="UTF-8"?>
<top-element>
    <complex-elem type="plain-number">1</complex-elem>
    <top-elem-name>myTopElement</top-elem-name>
</top-element>

The following code will deserialize it, then serialize it again and overwrite the file:

XmlSerializer serializer = new XmlSerializer(typeof(topelement));
string path = ... // path of the file on my disk
topelement rawData = null;
using (FileStream reader = new FileStream(path, FileMode.Open))
{
    rawData = (topelement)serializer.Deserialize(reader);
}
XmlSerializerNamespaces noNamespace
    = new XmlSerializerNamespaces(new XmlQualifiedName[] { new XmlQualifiedName("", "") });
    // I use it to prevent adding a namespace during serializing
using (XmlWriter wr = XmlWriter.Create(path))
{
    serializer.Serialize(wr, rawData, noNamespace);
}

But the overwritten file looks like this:

<?xml version="1.0" encoding="utf-8"?>
<top-element>
    <complex-elem />
    <top-elem-name>myTopElement</top-elem-name>
</top-element>

Ie the data inside complex-elem got lost! Debugging shows that the deserialized content already contains null where it shouldn't (see picture).

在此输入图像描述


This is the xsd schema:

<?xml version="1.0" encoding="utf-8"?>
<xs:schema elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema">

  <xs:element name="top-element">
    <xs:complexType>
      <xs:sequence>
        <xs:element ref="complex-elem" />
        <xs:element ref="top-elem-name" />
      </xs:sequence>
    </xs:complexType>
  </xs:element>

  <xs:element name="complex-elem">
    <xs:complexType>
      <xs:choice>
        <xs:element ref="plain-number" />
      </xs:choice>
    </xs:complexType>
  </xs:element>

  <xs:element name="plain-number" type="xs:string" />
  <xs:element name="top-elem-name" type="xs:string" />

</xs:schema>

And here is the result of calling xsd.exe (the comments are German):

//------------------------------------------------------------------------------
// <auto-generated>
//     Dieser Code wurde von einem Tool generiert.
//     Laufzeitversion:4.0.30319.42000
//
//     Änderungen an dieser Datei können falsches Verhalten verursachen und gehen verloren, wenn
//     der Code erneut generiert wird.
// </auto-generated>
//------------------------------------------------------------------------------

using System.Xml.Serialization;

// 
// Dieser Quellcode wurde automatisch generiert von xsd, Version=4.6.1055.0.
// 


/// <remarks/>
[System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")]
[System.SerializableAttribute()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType=true)]
[System.Xml.Serialization.XmlRootAttribute("top-element", Namespace="", IsNullable=false)]
public partial class topelement {

    private complexelem complexelemField;

    private string topelemnameField;

    /// <remarks/>
    [System.Xml.Serialization.XmlElementAttribute("complex-elem")]
    public complexelem complexelem {
        get {
            return this.complexelemField;
        }
        set {
            this.complexelemField = value;
        }
    }

    /// <remarks/>
    [System.Xml.Serialization.XmlElementAttribute("top-elem-name")]
    public string topelemname {
        get {
            return this.topelemnameField;
        }
        set {
            this.topelemnameField = value;
        }
    }
}

/// <remarks/>
[System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")]
[System.SerializableAttribute()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType=true)]
[System.Xml.Serialization.XmlRootAttribute("complex-elem", Namespace="", IsNullable=false)]
public partial class complexelem {

    private string itemField;

    /// <remarks/>
    [System.Xml.Serialization.XmlElementAttribute("plain-number")]
    public string Item {
        get {
            return this.itemField;
        }
        set {
            this.itemField = value;
        }
    }
}

The XML sample you try to deserialize doesn't validate against the XSD schema you provided.

If you try to validate the XML, you'll get three validation errors:

  • Cvc-complex-type.3.2.2: Attribute 'type' Is Not Allowed To Appear In Element 'complex-elem'., Line '2', Column '39'.
  • Cvc-complex-type.2.3: Element 'complex-elem' Cannot Have Character [children], Because The Type's Content Type Is Element-only., Line '2', Column '55'.
  • Cvc-complex-type.2.4.b: The Content Of Element 'complex-elem' Is Not Complete. One Of '{plain-number}' Is Expected., Line '2', Column '55'.

So either change your XML to the following one:

<?xml version="1.0" encoding="UTF-8"?>
<top-element>
    <complex-elem>
        <plain-number>1</plain-number>
    </complex-elem>
    <top-elem-name>myTopElement</top-elem-name>
</top-element>

... or change your complex-elem schema definition to this one:

<xs:element name="complex-elem">
    <xs:complexType>
        <xs:simpleContent>
            <xs:extension base="xs:string">
                <xs:attribute name="type" type="xs:string" />
            </xs:extension>
       </xs:simpleContent>
   </xs:complexType>
</xs:element>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM