订购和XMLRoot属性中的Xml序列化问题

时间:2019-03-06 20:45:37

标签: c# xml serialization deserialization xmlserializer

我正在编写一个类来序列化KiCAD BOM /示意图文件。该类工作正常,可以正确地序列化和反序列化原始文件,但是我遇到两个无法解决的小问题。 这是课程代码:

until [ "$(ps -p $pid | grep -c $pid)" = '0' ] || [ $count -gt $kwait ]
# ..... ^^^ ....................... ^^

第一个问题是[XmlRoot(ElementName = "export")] public class SchematicExport { [XmlAttribute] public const string version = "D"; public Design design { get; set; } [XmlArrayItem(typeof(Component), ElementName = "comp")] public List<Component> components; [XmlArrayItem(typeof(LibPart), ElementName = "libpart")] public List<LibPart> libparts; [XmlArrayItem(typeof(Library), ElementName = "library")] public List<Library> libraries; [XmlArrayItem(typeof(Net), ElementName = "net")] public List<Net> nets; public class Design { public string source { get; set; } public string date { get => _date.ToString("dd/MM/yyyy HH:mm:ss"); set => _date = DateTime.Parse(value); } private DateTime _date; public string tool { get; set; } [XmlElement("sheet")] public List<Sheet> sheets { get; } public class Sheet { [XmlAttribute] public int number { get; set; } [XmlAttribute] public string name { get; set; } [XmlAttribute] public string tstamps { get; set; } public TitleBlock title_block { get; set; } public class TitleBlock { public string title { get; set; } public string company { get; set; } public string rev { get; set; } public string date { get => _date.ToString("yyyy-MM-dd"); set => _date = DateTime.Parse(value); } private DateTime _date; public string source { get; set; } [XmlElement("comment")] public List<Comment> comments; public class Comment { [XmlAttribute] public int number; [XmlAttribute] public string value; public Comment() { } public Comment(int number, string value) : this() { this.number = number; this.value = value; } } public TitleBlock() { comments = new List<Comment>(); _date = DateTime.Now; } public TitleBlock(string title, string company, string rev, string date, string source) { this.title = title; this.company = company; this.rev = rev; this.date = date; this.source = source; } } public Sheet() { title_block = new TitleBlock(); tstamps = DateTime.Now.ToFileTime().ToString("X8"); } public Sheet(int number, string name) : this() { this.number = number; this.name = name; } } public Design() { sheets = new List<Sheet>(); _date = DateTime.Now; } public Design(string source, string date, string tool) : this() { this.source = source; this.date = date; this.tool = tool; } } public class Component { [XmlAttribute("ref")] public string reference { get; set; } public string value { get; set; } public string footprint { get; set; } public string datasheet { get; set; } [XmlArrayItem(typeof(Field), ElementName = "field")] public List<Field> fields; public LibSource libsource { get; set; } public SheetPath sheetpath { get; set; } public string tstamp { get; set; } public class LibSource { [XmlAttribute] public string lib { get; set; } [XmlAttribute] public string part { get; set; } [XmlAttribute] public string description { get; set; } } public class SheetPath { [XmlAttribute] public string names { get; set; } [XmlAttribute] public string tstamps { get; set; } } public Component() { fields = new List<Field>(); libsource = new LibSource(); sheetpath = new SheetPath(); tstamp = DateTime.Now.ToFileTime().ToString("X8"); } public Component(string reference, string value, string footprint) : this() { this.reference = reference; this.value = value; this.footprint = footprint; } } public class LibPart { [XmlAttribute] public string lib { get; set; } [XmlAttribute] public string part { get; set; } [XmlArrayItem(typeof(Field), ElementName = "field")] public List<Field> fields; [XmlArrayItem(typeof(string), ElementName = "fp")] public List<string> footprints; [XmlArrayItem(typeof(Pin), ElementName = "pin")] public List<Pin> pins; public class Pin { [XmlAttribute] public string num { get; set; } [XmlAttribute] public string name { get; set; } [XmlAttribute] public string type { get; set; } public Pin() { } public Pin(string num, string name, string type) : this() { this.num = num; this.name = name; this.type = type; } } public LibPart() { fields = new List<Field>(); footprints = new List<string>(); pins = new List<Pin>(); } public LibPart(string lib, string part) : this() { this.lib = lib; this.part = part; } } public class Library { [XmlAttribute] public string logical { get; set; } public string uri { get; set; } public Library() { } public Library(string logical, string uri) : this() { this.logical = logical; this.uri = uri; } } public class Net { [XmlAttribute] public string code { get; set; } [XmlAttribute] public string name { get; set; } [XmlElement("node")] public List<Node> nodes; public class Node { [XmlAttribute("ref")] public string reference { get; set; } [XmlAttribute] public string pin { get; set; } public Node() { } public Node(string reference, string pin) : this() { this.reference = reference; this.pin = pin; } } public Net() { nodes = new List<Node>(); } public Net(string code, string name) : this() { this.code = code; this.name = name; } } public class Field { [XmlAttribute] public string name { get; set; } [XmlText] public string value { get; set; } public Field() { } public Field(string name, string value) : this() { this.name = name; this.value = value; } } public SchematicExport() { design = new Design(); components = new List<Component>(); libparts = new List<LibPart>(); libraries = new List<Library>(); nets = new List<Net>(); } public void Serialze(string filename) { XmlSerializer _xmlSerializer = new XmlSerializer(typeof(SchematicExport)); TextWriter _textWriter = new StreamWriter(filename); _xmlSerializer.Serialize(_textWriter, this); } public static SchematicExport Create(string filename) { if (!System.IO.File.Exists(filename)) throw new Exception("File not existing"); SchematicExport _schematicExport = null; XmlSerializer _serializer = new XmlSerializer(typeof(SchematicExport)); StreamReader _reader = new StreamReader(filename); _schematicExport = (SchematicExport)_serializer.Deserialize(_reader); return _schematicExport; } } 的{​​{1}}元素。我希望XmlRoot属性会出现在根XML标记内,但不会:

SchematicExport

第二个问题是元素的顺序(好吧,这不是一个大问题,因为标签不依赖于顺序),我尝试使用version属性来强制使用它,但是我只得到了多个<export xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> 例外。

我只是在序列化程序中做了一些小修改就删除了XmlElement(Order=nn)Reflection

xmlns:xsi

即使我可以反序列化这样的Xml,我也发现了另一个(更恶意的)问题:

xmlns:xsd

产生的序列化不完整:

public void Serialze(string filename)
{
    XmlSerializer _xmlSerializer = new XmlSerializer(typeof(SchematicExport)); 
    XmlSerializerNamespaces _serializerNamespaces = new XmlSerializerNamespaces();

    _serializerNamespaces.Add("", "");

    using (TextWriter _textWriter = new StreamWriter(filename))
    {
        _xmlSerializer.Serialize(_textWriter, this, _serializerNamespaces);
    }
}

如您所见,?xml version="1.0" encoding="UTF-8"?> <export version="D"> <design> <source>C:\Users\m.santucci\Documents\Progetti\Viper\Schede Viper\V1-10A119\V1-10A119.sch</source> <date>07/03/2019 10:33:01</date> <tool>Eeschema (5.0.2)-1</tool> <sheet number="1" name="/" tstamps="/"> <title_block> <title>V1-10A119</title> <company>ROB.INT. s.r.l.</company> <rev>01</rev> <date>2019-02-25</date> <source>V1-10A119.sch</source> <comment number="1" value="Michele Santucci"/> <comment number="2" value=""/> <comment number="3" value=""/> <comment number="4" value=""/> </title_block> </sheet> </design> <components> <comp ref="U5"> <value>ADM3101E</value> <footprint>Analog:LFCSP-12_EP_3x3_Pitch0.5mm</footprint> <datasheet>https://www.analog.com/media/en/technical-documentation/data-sheets/adm3101e.pdf</datasheet> <fields> <field name="Code">820-9369 </field> <field name="P/N">ADM3101EACPZ-250R7 </field> <field name="Productor">Analog</field> <field name="Provider">RS</field> <field name="manf#">ADM3101EACPZ-250R7 </field> </fields> <libsource lib="V1-10A119-rescue" part="ADM3101E-analog" description=""/> <sheetpath names="/MICRO/" tstamps="/5D2A20EE/"/> <tstamp>5C83E717</tstamp> </comp> <comp ref="C35"> <value>100nF</value> <footprint>Capacitors_SMD:C_0603</footprint> <datasheet>~</datasheet> <fields> <field name="Code">135-8345 </field> <field name="P/N">06035G104ZAT2A</field> <field name="Productor">AVX</field> <field name="Provider">RS</field> <field name="manf#">06035G104ZAT2A</field> </fields> <libsource lib="V1-10A119-rescue" part="C_Small-Device" description=""/> <sheetpath names="/MICRO/" tstamps="/5D2A20EE/"/> <tstamp>5C84AA07</tstamp> </comp> <comp ref="C37"> <value>100nF</value> <footprint>Capacitors_SMD:C_0603</footprint> <datasheet>~</datasheet> <fields> <field name="Code">135-8345 </field> <field name="P/N">06035G104ZAT2A</field> <field name="Productor">AVX</field> <field name="Provider">RS</field> <field name="manf#">06035G104ZAT2A</field> </fields> <libsource lib="V1-10A119-rescue" part="C_Small-Device" description=""/> <sheetpath names="/MICRO/" tstamps="/5D2A20EE/"/> <tstamp>5C84AB0B</tstamp> </comp> <comp ref="C34"> <value>100nF</value> <footprint>Capacitors_SMD:C_0603</footprint> <datasheet>~</datasheet> <fields> <field name="Code">135-8345 </field> <field name="P/N">06035G104ZAT2A</field> <field name="Productor">AVX</field> <field name="Provider">RS</field> <field name="manf#">06035G104ZAT2A</field> </fields> <libsource lib="V1-10A119-rescue" part="C_Small-Device" description=""/> <sheetpath names="/MICRO/" tstamps="/5D2A20EE/"/> <tstamp>5C84AB65</tstamp> </comp> <comp ref="C38"> <value>100nF</value> <footprint>Capacitors_SMD:C_0603</footprint> <datasheet>~</datasheet> <fields> <field name="Code">135-8345 </field> <field name="P/N">06035G104ZAT2A</field> <field name="Productor">AVX</field> <field name="Provider">RS</field> <field name="manf#">06035G104ZAT2A</field> </fields> <libsource lib="V1-10A119-rescue" part="C_Small-Device" description=""/> <sheetpath names="/MICRO/" tstamps="/5D2A20EE/"/> <tstamp>5C84AC22</tstamp> </comp> <comp ref="C36"> <value>100nF</value> <footprint>Capacitors_SMD:C_0603</footprint> <datasheet>~</datasheet> <fields> <field name="Code">135-8345 </field> <field name="P/N">06035G104ZAT2A</field> <field name="Productor">AVX</field> <field name="Provider">RS</field> <field name="manf#">06035G104ZAT2A</field> </fields> <libsource lib="V1-10A119-rescue" part="C_Small-Device" description=""/> <sheetpath names="/MICRO/" tstamps="/5D2A20EE/"/> <tstamp>5C84D1BA</tstamp> </comp> </components> <libparts> <libpart lib="conn" part="CONN_2"> <description>Symbole general de connecteur</description> <fields> <field name="Reference">P</field> <field name="Value">CONN_2</field> </fields> <pins> <pin num="1" name="P1" type="passive"/> <pin num="2" name="PM" type="passive"/> </pins> </libpart> </libparts> <libraries> <library logical="V1-10A119-rescue"> <uri>C:\Users\m.santucci\Documents\Progetti\Viper\Schede Viper\V1-10A119/V1-10A119-rescue.lib</uri> </library> <library logical="conn"> <uri>C:/Users/Public/Documents/Kicad/library/conn.lib</uri> </library> </libraries> <nets> <net code="200" name="VBUS"> <node ref="P9" pin="2"/> <node ref="U3" pin="3"/> <node ref="C12" pin="2"/> <node ref="C30" pin="2"/> <node ref="U4" pin="3"/> </net> <net code="201" name="Net-(LD13-Pad1)"> <node ref="LD13" pin="1"/> <node ref="R37" pin="1"/> </net> </nets> </export> 标签(comp部分)和<?xml version="1.0" encoding="UTF-8"?> <export version="D"> <design> <source>C:\Users\m.santucci\Documents\Progetti\Viper\Schede Viper\V1-10A119\V1-10A119.sch</source> <date>07/03/2019 10:33:01</date> <tool>Eeschema (5.0.2)-1</tool> <sheet number="1" name="/" tstamps="/"> <title_block> <title>V1-10A119</title> <company>ROB.INT. s.r.l.</company> <rev>01</rev> <date>2019-02-25</date> <source>V1-10A119.sch</source> <comment number="1" value="Michele Santucci"/> <comment number="2" value=""/> <comment number="3" value=""/> <comment number="4" value=""/> </title_block> </sheet> </design> <components> <comp ref="U5"> <value>ADM3101E</value> <footprint>Analog:LFCSP-12_EP_3x3_Pitch0.5mm</footprint> <fields> <field name="Code">820-9369 </field> <field name="P/N">ADM3101EACPZ-250R7 </field> <field name="Productor">Analog</field> <field name="Provider">RS</field> <field name="manf#">ADM3101EACPZ-250R7 </field> </fields> <libsource lib="V1-10A119-rescue" part="ADM3101E-analog" description=""/> <sheetpath names="/MICRO/" tstamps="/5D2A20EE/"/> <tstamp>5C83E717</tstamp> </comp> <comp ref="C35"> <value>100nF</value> <footprint>Capacitors_SMD:C_0603</footprint> <fields> <field name="Code">135-8345 </field> <field name="P/N">06035G104ZAT2A</field> <field name="Productor">AVX</field> <field name="Provider">RS</field> <field name="manf#">06035G104ZAT2A</field> </fields> <libsource lib="V1-10A119-rescue" part="C_Small-Device" description=""/> <sheetpath names="/MICRO/" tstamps="/5D2A20EE/"/> <tstamp>5C84AA07</tstamp> </comp> <comp ref="C37"> <value>100nF</value> <footprint>Capacitors_SMD:C_0603</footprint> <fields> <field name="Code">135-8345 </field> <field name="P/N">06035G104ZAT2A</field> <field name="Productor">AVX</field> <field name="Provider">RS</field> <field name="manf#">06035G104ZAT2A</field> </fields> <libsource lib="V1-10A119-rescue" part="C_Small-Device" description=""/> <sheetpath names="/MICRO/" tstamps="/5D2A20EE/"/> <tstamp>5C84AB0B</tstamp> </comp> <comp ref="C34"> <value>100nF</value> <footprint>Capacitors_SMD:C_0603</footprint> <fields> <field name="Code">135-8345 </field> <field name="P/N">06035G104ZAT2A</field> <field name="Productor">AVX</field> <field name="Provider">RS</field> <field name="manf#">06035G104ZAT2A</field> </fields> <libsource lib="V1-10A119-rescue" part="C_Small-Device" description=""/> <sheetpath names="/MICRO/" tstamps="/5D2A20EE/"/> <tstamp>5C84AB65</tstamp> </comp> <comp ref="C38"> <value>100nF</value> <footprint>Capacitors_SMD:C_0603</footprint> <fields> <field name="Code">135-8345 </field> <field name="P/N">06035G104ZAT2A</field> <field name="Productor">AVX</field> <field name="Provider">RS</field> <field name="manf#">06035G104ZAT2A</field> </fields> <libsource lib="V1-10A119-rescue" part="C_Small-Device" description=""/> <sheetpath names="/MICRO/" tstamps="/5D2A20EE/"/> <tstamp>5C84AC22</tstamp> </comp> <comp ref="C36"> <value>100nF</value> <footprint>Capacitors_SMD:C_0603</footprint> <fields> <field name="Code">135-8345 </field> <field name="P/N">06035G104ZAT2A</field> <field name="Productor">AVX</field> <field name="Provider">RS</field> <field name="manf#">06035G104ZAT2A</field> </fields> <libsource lib="V1-10A119-rescue" part="C_Small-Device" description=""/> <sheetpath names="/MICRO/" tstamps="/5D2A20EE/"/> <tstamp>5C84D1BA</tstamp> </comp> </components> <libparts> <libpart lib="conn" part="CONN_2"> <fields> <field name="Reference">P</field> <field name="Value">CONN_2</field> </fields> <pins> <pin num="1" name="P1" type="passive"/> <pin num="2" name="PM" type="passive"/> </pins> </libpart> </libparts> <libraries> <library logical="V1-10A119-rescue"> <uri>C:\Users\m.santucci\Documents\Progetti\Viper\Schede Viper\V1-10A119/V1-10A119-rescue.lib</uri> </library> <library logical="conn"> <uri>C:/Users/Public/Documents/Kicad/library/conn.lib</uri> </library> </libraries> <nets> <net code="200" name="VBUS"> <node ref="P9" pin="2"/> <node ref="U3" pin="3"/> <node ref="C12" pin="2"/> <node ref="C30" pin="2"/> <node ref="U4" pin="3"/> </net> <net code="201" name="Net-(LD13-Pad1)"> <node ref="LD13" pin="1"/> <node ref="R37" pin="1"/> </net> </nets> </export> (libpart部分)都丢失了。

我无法真正理解错误的出处,但显然问题不是反序列化:

Debug session

1 个答案:

答案 0 :(得分:1)

第一个问题是在XmlRoot元素上。我希望version属性会出现在XMLRoot标记内,但不会出现。

Introducing XML Serialization 中所述,XmlSerializer不会序列化const成员,即使在公开时也是如此:

  

XML序列化仅将对象的公共字段和属性值序列化为XML流。 XML序列化不包含类型信息。

     

     

XML序列化不会转换方法,索引器,私有字段或只读属性(只读集合除外)。要序列化所有对象的公共和私有字段和属性,请使用DataContractSerializer而不是XML序列化。

解决此问题的最简单方法是为该版本添加代理属性,如下所示:

public const string version = "D";

[XmlAttribute("version")]
[System.ComponentModel.Browsable(false), System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never), System.Diagnostics.DebuggerBrowsable(System.Diagnostics.DebuggerBrowsableState.Never)]
public string Version { get { return version; } set { /* Do nothing */ } }

该属性必须是公共的,但是您可以通过属性BrowsableEditorBrowsableDebuggerBrowsable降低其可见性。

第二个问题是元素的顺序(好吧,这不是一个大问题,因为标签不依赖于顺序),我尝试使用XmlElement(Order=nn)属性来强制使用它,但是我得到了许多{{ 1}}例外。

您没有提供此示例,但是我能够重现以下问题。如果我在Reflection的集合成员的 some 而不是 all 上设置了XmlArrayAttribute.Order,则会出现以下异常:

SchematicExport

演示小提琴#1 here

解决方案是遵循异常消息中的建议,并将order属性应用于类中的所有可序列化成员。

因此System.InvalidOperationException: There was an error reflecting type 'SchematicExport'. ---> System.InvalidOperationException: Inconsistent sequencing: if used on one of the class's members, the 'Order' property is required on all particle-like members, please explicitly set 'Order' using XmlElement, XmlAnyElement or XmlArray custom attribute on class member 'nets'. at System.Xml.Serialization.XmlReflectionImporter.InitializeStructMembers(StructMapping mapping, StructModel model, Boolean openModel, String typeName, RecursionLimiter limiter) at System.Xml.Serialization.XmlReflectionImporter.ImportStructLikeMapping(StructModel model, String ns, Boolean openModel, XmlAttributes a, RecursionLimiter limiter) at System.Xml.Serialization.XmlReflectionImporter.ImportTypeMapping(TypeModel model, String ns, ImportContext context, String dataType, XmlAttributes a, Boolean repeats, Boolean openModel, RecursionLimiter limiter) 应该类似于:

SchematicExport

请注意,设置元素顺序不仅会在序列化过程中对元素进行重新排序,还会要求,在反序列化过程中它们处于该顺序。

偶然地,您需要在[XmlRoot(ElementName = "export")] public partial class SchematicExport { public const string version = "D"; [XmlAttribute("version")] [System.ComponentModel.Browsable(false), System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never), System.Diagnostics.DebuggerBrowsable(System.Diagnostics.DebuggerBrowsableState.Never)] public string Version { get { return version; } set { /* Do nothing */ } } [XmlElement(Order = 1)] public Design design { get; set; } [XmlArray(Order = 2)] [XmlArrayItem(typeof(Component), ElementName = "comp")] public List<Component> components; [XmlArray(Order = 3)] [XmlArrayItem(typeof(LibPart), ElementName = "libpart")] public List<LibPart> libparts; [XmlArray(Order = 4)] [XmlArrayItem(typeof(Library), ElementName = "library")] public List<Library> libraries; [XmlArray(Order = 5)] [XmlArrayItem(typeof(Net), ElementName = "net")] public List<Net> nets; } 中关闭SchematicExport.Serialize(string)。最简单的方法是通过using语句:

StreamWriter

您的问题中显示的此方法的第一个版本不执行此操作。

演示小提琴#2 here