【问题标题】:C# XML deserialization issues / Unable to generate a temporary class (result=1)C# XML 反序列化问题/无法生成临时类(结果=1)
【发布时间】:2021-12-06 05:10:53
【问题描述】:

又是我。

我目前正忙于反序列化特定的 XML 文件,这让我很头疼。

需要反序列化的XML:

<AuditEntryData>
    <AuditEntryValue name="Supplier name" newValue="Assagne Corp." type="Text" />
    <AuditEntryValue name="MODDATETIME" oldValue="2021-09-15T17:07:37.0000000Z" newValue="2021-09-15T17:29:27.0000000Z" type="DateTime" />
    <AuditEntryTableValues>
        <T name="InvoiceItems">
            <Columns>
                <C name="Name" type="Text" />
                <C name="Accounting-Key" type="Text" />
                <C name="AdditionalColumn" type="Text" />
                <C name="Date" type="Date" />
                <C name="Value" type="Number" />
            </Columns>
            <OldValues>
                <R>
                    <C>Oh Long Johnson</C>
                    <C>23ufztg3u4ghf</C>
                    <C>Test33</C>
                    <C>2021-02-10T00:00:00.0000000Z</C>
                    <C>18.73</C>
                </R>
            </OldValues>
            <NewValues>
                <R>
                    <C>John Smith</C>
                    <C>23ufztg3u4ghf</C>
                    <C>Test33</C>
                    <C>2021-02-10T00:00:00.0000000Z</C>
                    <C>18.73</C>
                </R>
                <R>
                    <C>Johnathan Smith</C>
                    <C>eui5dctmcotgu</C>
                    <C>Test22</C>
                    <C>2021-09-15T00:00:00.0000000Z</C>
                    <C>13.12</C>
                </R>
            </NewValues>
        </T>
    </AuditEntryTableValues>
</AuditEntryData>

用xsd生成的类文件:

/// <remarks/>
[System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.8.3928.0")]
[System.SerializableAttribute()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType=true)]
[System.Xml.Serialization.XmlRootAttribute(Namespace="", IsNullable=false)]
public partial class C {
    
    private string nameField;
    
    private string typeField;
    
    /// <remarks/>
    [System.Xml.Serialization.XmlAttributeAttribute()]
    public string name {
        get {
            return this.nameField;
        }
        set {
            this.nameField = value;
        }
    }
    
    /// <remarks/>
    [System.Xml.Serialization.XmlAttributeAttribute()]
    public string type {
        get {
            return this.typeField;
        }
        set {
            this.typeField = value;
        }
    }
}

/// <remarks/>
[System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.8.3928.0")]
[System.SerializableAttribute()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType=true)]
[System.Xml.Serialization.XmlRootAttribute(Namespace="", IsNullable=false)]
public partial class R {
    
    private C[] cField;
    
    /// <remarks/>
    [System.Xml.Serialization.XmlElementAttribute("C")]
    public C[] C {
        get {
            return this.cField;
        }
        set {
            this.cField = value;
        }
    }
}

/// <remarks/>
[System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.8.3928.0")]
[System.SerializableAttribute()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType=true)]
[System.Xml.Serialization.XmlRootAttribute(Namespace="", IsNullable=false)]
public partial class AuditEntryData {
    
    private object[] itemsField;
    
    /// <remarks/>
    [System.Xml.Serialization.XmlElementAttribute("AuditEntryTableValues", typeof(AuditEntryDataAuditEntryTableValues), Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
    [System.Xml.Serialization.XmlElementAttribute("AuditEntryValue", typeof(AuditEntryDataAuditEntryValue), Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
    [System.Xml.Serialization.XmlElementAttribute("C", typeof(C))]
    [System.Xml.Serialization.XmlElementAttribute("R", typeof(R))]
    public object[] Items {
        get {
            return this.itemsField;
        }
        set {
            this.itemsField = value;
        }
    }
}

/// <remarks/>
[System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.8.3928.0")]
[System.SerializableAttribute()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType=true)]
public partial class AuditEntryDataAuditEntryTableValues {
    
    private AuditEntryDataAuditEntryTableValuesT[] tField;
    
    /// <remarks/>
    [System.Xml.Serialization.XmlElementAttribute("T", Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
    public AuditEntryDataAuditEntryTableValuesT[] T {
        get {
            return this.tField;
        }
        set {
            this.tField = value;
        }
    }
}

/// <remarks/>
[System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.8.3928.0")]
[System.SerializableAttribute()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType=true)]
public partial class AuditEntryDataAuditEntryTableValuesT {
    
    private C[][] columnsField;
    
    private C[][][] oldValuesField;
    
    private C[][][] newValuesField;
    
    private string nameField;
    
    /// <remarks/>
    [System.Xml.Serialization.XmlArrayAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
    [System.Xml.Serialization.XmlArrayItemAttribute("C", typeof(C), IsNullable=false)]
    public C[][] Columns {
        get {
            return this.columnsField;
        }
        set {
            this.columnsField = value;
        }
    }
    
    /// <remarks/>
    [System.Xml.Serialization.XmlArrayAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
    [System.Xml.Serialization.XmlArrayItemAttribute("R", typeof(C[]), IsNullable=false)]
    [System.Xml.Serialization.XmlArrayItemAttribute("C", typeof(C), IsNullable=false, NestingLevel=1)]
    public C[][][] OldValues {
        get {
            return this.oldValuesField;
        }
        set {
            this.oldValuesField = value;
        }
    }
    
    /// <remarks/>
    [System.Xml.Serialization.XmlArrayAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
    [System.Xml.Serialization.XmlArrayItemAttribute("R", typeof(C[]), IsNullable=false)]
    [System.Xml.Serialization.XmlArrayItemAttribute("C", typeof(C), IsNullable=false, NestingLevel=1)]
    public C[][][] NewValues {
        get {
            return this.newValuesField;
        }
        set {
            this.newValuesField = value;
        }
    }
    
    /// <remarks/>
    [System.Xml.Serialization.XmlAttributeAttribute()]
    public string name {
        get {
            return this.nameField;
        }
        set {
            this.nameField = value;
        }
    }
}

/// <remarks/>
[System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.8.3928.0")]
[System.SerializableAttribute()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType=true)]
public partial class AuditEntryDataAuditEntryValue {
    
    private string nameField;
    
    private string newValueField;
    
    private string typeField;
    
    private string oldValueField;
    
    /// <remarks/>
    [System.Xml.Serialization.XmlAttributeAttribute()]
    public string name {
        get {
            return this.nameField;
        }
        set {
            this.nameField = value;
        }
    }
    
    /// <remarks/>
    [System.Xml.Serialization.XmlAttributeAttribute()]
    public string newValue {
        get {
            return this.newValueField;
        }
        set {
            this.newValueField = value;
        }
    }
    
    /// <remarks/>
    [System.Xml.Serialization.XmlAttributeAttribute()]
    public string type {
        get {
            return this.typeField;
        }
        set {
            this.typeField = value;
        }
    }
    
    /// <remarks/>
    [System.Xml.Serialization.XmlAttributeAttribute()]
    public string oldValue {
        get {
            return this.oldValueField;
        }
        set {
            this.oldValueField = value;
        }
    }
}

反序列化 xml 给我以下错误:

多维数组:

Unable to generate a temporary class (result=1).
error CS0030: Cannot convert type 'C[]' to 'C'
error CS0030: Cannot convert type 'C[][]' to 'C[]'
error CS0029: Cannot implicitly convert type 'C' to 'C[]'
error CS0029: Cannot implicitly convert type 'C[]' to 'C[][]

一维数组(修改类文件后):

Unable to generate a temporary class (result=1).
error CS0030: Cannot convert type 'C' to 'C[]'
error CS0029: Cannot implicitly convert type 'C[]' to 'C'

xml 是由外部程序生成的,所以我无法控制它。因此无法更改格式。 如果我删除/注释掉类型属性声明,我可以加载 XML,但它不会加载 OldValuesNewValues

有人能指出正确的方向吗?

【问题讨论】:

    标签: c# xml deserialization


    【解决方案1】:

    尝试以下:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Xml;
    using System.Xml.Serialization;
    namespace ConsoleApplication2
    {
        class Program
        {
            const string FILE = @"c:\TEMP\TEST.XML";
            static void Main(string[] args)
            {
                XmlReader reader = XmlReader.Create(FILE);
                XmlSerializer serializer = new XmlSerializer(typeof(AuditEntryData));
                AuditEntryData auditEntryData = (AuditEntryData)serializer.Deserialize(reader);
    
            }
        }
        public class AuditEntryData
        {
            [XmlElement()]
            public AuditEntryValue[] AuditEntryValue { get; set; }
    
            [XmlArray("AuditEntryTableValues")]
            [XmlArrayItem("T")]
            public AuditEntryTableValue[] AuditEntryTableValue { get; set; }
        }
        public class AuditEntryValue
        {
            [XmlAttribute]
            public string name { get; set; }
            [XmlAttribute]
            public string newValue { get; set; }
            [XmlAttribute]
            public string oldValue { get; set; }
            [XmlAttribute]
            public string type { get; set; }
    
        }
        public class AuditEntryTableValue
        {
            [XmlAttribute]
            public string name { get; set; }
    
            [XmlArray("Columns")]
            [XmlArrayItem("C")]
            public Column[] Columns { get; set; }
    
            [XmlArray("OldValues")]
            [XmlArrayItem("R")]
            public OldValue[] OldValues { get; set; }
    
            [XmlArray("NewValues")]
            [XmlArrayItem("R")]
            public NewValue[] NewValues { get; set; }
        }
        public class Column
        {
            [XmlAttribute]
            public string name { get; set; }
            [XmlAttribute]
            public string type { get; set; }
        }
        public class OldValue
        {
            [XmlElement]
            public string[] C{ get; set; }
        }
        public class NewValue
        {
            [XmlElement]
            public string[] C { get; set; }
        }
    }
    

    【讨论】:

    • 谢谢你,你是一个救生员。这不是第一次遇到这个问题,但我不记得上次如何解决它。我可能最终像你一样手动完成。我对此表示衷心的感谢。当涉及到像 op 中的 XML 数据时,有没有办法让 xsd 更可靠?
    • 不是xsd。问题是 xml 和架构不匹配。在针对模式生成 XML 文件时,应始终对其进行验证。我见过太多的情况,人们得到的 xml 文件与架构不匹配,必须联系生成 xml 的人来解决问题。
    • 该架构是使用 xsd 从该文件生成的。从技术上讲,xsd 产生了这种“垃圾”。在大多数情况下,它确实可以毫不费力地工作,但是在这种特定情况下(或我过去遇到的另一种情况),当使用 xsd 创建 shema 时,它并没有那么好。
    • XML 到架构的效果不如架构到 xml。用于创建架构的 xml 文件越大,获得的结果就越好。将 xml 转换为模式的工具不知道类型或数组。不得不做很多猜测。根据需求创建架构效果更好。
    【解决方案2】:

    这是一个有效的简化示例。 只需使用XML.Run()。 通过指定ElementName,OldValues 和 NewValues 类可能只能合并为一个类。

    public class XML
        {
            private readonly string xml = @"
    <AuditEntryData>
        <AuditEntryValue name=""Supplier name"" newValue=""Assagne Corp."" type=""Text"" />
        <AuditEntryValue name=""MODDATETIME"" oldValue=""2021-09-15T17:07:37.0000000Z"" newValue=""2021-09-15T17:29:27.0000000Z"" type=""DateTime"" />
        <AuditEntryTableValues>
            <T name=""InvoiceItems"">
                <Columns>
                    <C name=""Name"" type=""Text"" />
                    <C name=""Accounting-Key"" type=""Text"" />
                    <C name=""AdditionalColumn"" type=""Text"" />
                    <C name=""Date"" type=""Date"" />
                    <C name=""Value"" type=""Number"" />
                </Columns>
                <OldValues>
                    <R>
                        <C>Oh Long Johnson</C>
                        <C>23ufztg3u4ghf</C>
                        <C>Test33</C>
                        <C>2021-02-10T00:00:00.0000000Z</C>
                        <C>18.73</C>
                    </R>
                </OldValues>
                <NewValues>
                    <R>
                        <C>John Smith</C>
                        <C>23ufztg3u4ghf</C>
                        <C>Test33</C>
                        <C>2021-02-10T00:00:00.0000000Z</C>
                        <C>18.73</C>
                    </R>
                    <R>
                        <C>Johnathan Smith</C>
                        <C>eui5dctmcotgu</C>
                        <C>Test22</C>
                        <C>2021-09-15T00:00:00.0000000Z</C>
                        <C>13.12</C>
                    </R>
                </NewValues>
            </T>
        </AuditEntryTableValues>
    </AuditEntryData>
    ";
    
            public void Run()
            {
                var stream = new MemoryStream();
                var writer = new StreamWriter(stream);
                writer.Write(xml);
                writer.Flush();
                stream.Position = 0;
    
                var ser = new XmlSerializer(typeof(AuditEntryData));
                var o = (AuditEntryData)ser.Deserialize(stream);
    
            }
    
            [XmlRoot]
            public class AuditEntryData
            {
                [XmlElement("AuditEntryValue")]
                public List<AuditEntryValue> AuditEntryValues { get; set; }
    
                [XmlElement]
                public AuditEntryTableValues AuditEntryTableValues { get; set; }
    
            }
    
            public class AuditEntryValue
            {
                [XmlAttribute]
                public string name { get; set; }
                [XmlAttribute]
                public string oldValue { get; set; }
                [XmlAttribute]
                public string newValue { get; set; }
                [XmlAttribute]
                public string type { get; set; }
            }
    
            public class AuditEntryTableValues
            {
                [XmlElement]
                public T T { get; set; }
            }
    
            public class T
            {
                [XmlAttribute]
                public string name { get; set; }
    
                [XmlElement]
                public Columns Columns { get; set; }
    
                [XmlElement]
                public OldValues OldValues { get; set; }
    
                [XmlElement]
                public NewValues NewValues { get; set; }
            }
    
            public class Columns
            {
                [XmlElement(ElementName = "C", Type = typeof(C))]
                public List<C> Cs { get; set; }
            }
    
    
            public class C
            {
                [XmlAttribute]
                public string name { get; set; }
    
                [XmlAttribute]
                public string type { get; set; }
            }
    
            public class OldValues
            {
                [XmlElement]
                public R R { get; set; }
            }
    
            public class NewValues
            {
                [XmlElement]
                public R R { get; set; }
            }
    
            public class R
            {
                [XmlElement(ElementName = "C")]
                public List<string> Cs { get; set; }
            }
        }
    

    【讨论】:

    • 感谢您的加入。它会在生成的 JSON 中产生更多的嵌套,所以我会坚持使用 @jdweng 方法。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-03-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多