Потеря данных при использовании автоматически сгенерированного сериализатора
У меня есть файл xsd, который описывает небольшую схему. Я создал файл C# с помощью xsd.exe (я запустил эту команду в командной строке разработчика: xsd.exe smallSchema.xsd /classes /language:CS
) иметь возможность легко (де) сериализовать его. Я взял XML-файл, соответствующий этой схеме, и попытался десериализовать его, используя сгенерированный код. Но я заметил, что происходит потеря данных!
Кто-нибудь может указать мне на причину этой потери данных?
Это XML-файл, который я хочу десериализовать:
<?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>
Следующий код десериализует его, затем снова сериализует и перезаписывает файл:
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);
}
Но перезаписанный файл выглядит так:
<?xml version="1.0" encoding="utf-8"?>
<top-element>
<complex-elem />
<top-elem-name>myTopElement</top-elem-name>
</top-element>
Т.е. данные внутри complex-elem
потерялся! Отладка показывает, что десериализованный контент уже содержит null
где это не должно (см. изображение).
Это схема xsd:
<?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>
И вот результат вызова xsd.exe (комментарии на немецком языке):
//------------------------------------------------------------------------------
// <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;
}
}
}
1 ответ
Пример XML, который вы пытаетесь десериализовать, не проверяется по предоставленной вами схеме XSD.
Если вы попытаетесь проверить XML, вы получите три ошибки проверки:
- Cvc-complex-type.3.2.2: атрибут "тип" не может появляться в элементе "complex-elem"., Строка "2", столбец "39".
- Cvc-complex-type.2.3: Элемент 'complex-elem' не может иметь символа [children], поскольку тип содержимого типа - только для элемента., Строка '2', столбец '55'.
- Cvc-complex-type.2.4.b: Содержимое элемента 'complex-elem' не завершено. Ожидается одно из '{plain-number}'. Строка '2', столбец '55'.
Так что либо измените свой XML на следующий:
<?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>
... или поменяй свой complex-elem
Определение схемы к этому:
<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>