【问题标题】:Try to deserialize a XML file尝试反序列化 XML 文件
【发布时间】:2013-11-23 16:26:37
【问题描述】:

我用 xsd.exe 生成了以下类:

using System.Xml.Serialization;

[System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "2.0.50727.42")]
[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 ROOT {

private PersonBaseType pERSONField;

/// <remarks/>
public PersonBaseType PERSON {
    get {
        return this.pERSONField;
    }
    set {
        this.pERSONField = value;
    }
}
}

[System.Xml.Serialization.XmlIncludeAttribute(typeof(NotWorkerPersonType))]
[System.Xml.Serialization.XmlIncludeAttribute(typeof(WorkerPersonType))]
[System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "2.0.50727.42")]
[System.SerializableAttribute()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
public abstract partial class PersonBaseType {

private MotorVehicleType vEHICLEField;

public MotorVehicleType VEHICLE {
    get {
        return this.vEHICLEField;
    }
    set {
        this.vEHICLEField = value;
    }
}
}

[System.Xml.Serialization.XmlIncludeAttribute(typeof(CarVehicleType))]
[System.Xml.Serialization.XmlIncludeAttribute(typeof(AutobusVehicleType))]
[System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "2.0.50727.42")]
[System.SerializableAttribute()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
public abstract partial class MotorVehicleType {

private string nameField;

public string Name {
    get {
        return this.nameField;
    }
    set {
        this.nameField = value;
    }
}
}

[System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "2.0.50727.42")]
[System.SerializableAttribute()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
public partial class CarVehicleType : MotorVehicleType {
}

[System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "2.0.50727.42")]
[System.SerializableAttribute()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
public partial class AutobusVehicleType : MotorVehicleType {
}

[System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "2.0.50727.42")]
[System.SerializableAttribute()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
public partial class NotWorkerPersonType : PersonBaseType {   
}

[System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "2.0.50727.42")]
[System.SerializableAttribute()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
public partial class WorkerPersonType : PersonBaseType {
}

我已经使用工具 xsd.exe 和以下 xsd 架构生成了这个类:

<?xml version="1.0" encoding="UTF-8"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" elementFormDefault="qualified" attributeFormDefault="qualified">
<xsd:complexType name="PersonBaseType" abstract="true">
    <xsd:sequence>
        <xsd:element name="VEHICLE" type="MotorVehicleType" minOccurs="0" maxOccurs="1"/>
    </xsd:sequence>
</xsd:complexType>
<xsd:complexType name="WorkerPersonType">
    <xsd:complexContent>
        <xsd:restriction base="PersonBaseType">
            <xsd:sequence>
                <xsd:element name="VEHICLE" type="AutobusVehicleType" minOccurs="1" maxOccurs="1"/>
            </xsd:sequence>
        </xsd:restriction>
    </xsd:complexContent>
</xsd:complexType>
<xsd:complexType name="NotWorkerPersonType">
    <xsd:complexContent>
        <xsd:restriction base="PersonBaseType">
            <xsd:sequence>
                <xsd:element name="VEHICLE" type="CarVehicleType" minOccurs="0" maxOccurs="1"/>
            </xsd:sequence>
        </xsd:restriction>
    </xsd:complexContent>
</xsd:complexType>
<xsd:complexType name="MotorVehicleType" abstract="true">
    <xsd:sequence>
        <xsd:element name="Name" type="xsd:string" minOccurs="0" maxOccurs="1"/>
    </xsd:sequence>
</xsd:complexType>
<xsd:complexType name="AutobusVehicleType">
    <xsd:complexContent>
        <xsd:restriction base="MotorVehicleType">
            <xsd:sequence>
                <xsd:element name="Name" type="xsd:string" minOccurs="1" maxOccurs="1"/>
            </xsd:sequence>
        </xsd:restriction>
    </xsd:complexContent>
</xsd:complexType>
<xsd:complexType name="CarVehicleType">
    <xsd:complexContent>
        <xsd:restriction base="MotorVehicleType">
            <xsd:sequence>
                <xsd:element name="Name" type="xsd:string" minOccurs="0" maxOccurs="1"/>
            </xsd:sequence>
        </xsd:restriction>
    </xsd:complexContent>
</xsd:complexType>
<xsd:element name="ROOT">
    <xsd:annotation>
        <xsd:documentation>Root element</xsd:documentation>
    </xsd:annotation>
    <xsd:complexType>
        <xsd:sequence>
            <xsd:element name="PERSON" type="PersonBaseType" minOccurs="1" maxOccurs="1"/>
        </xsd:sequence>
    </xsd:complexType>
</xsd:element>
</xsd:schema>

我尝试反序列化这个 xml:

<?xml version="1.0" encoding="UTF-8"?>
<ROOT xmlns:xxx="http://www.w3.org/2001/XMLSchema-instance" xxx:schemaLocation="C:\Users\SIGFRID\Documents\Visual Studio 2012\Projects\sample\ConsoleApplication1\ConsoleApplication1\MySample.xsd">
<PERSON xxx:type="WorkerPersonType">
    <VEHICLE>
        <Name>VOLVO</Name>
    </VEHICLE>
</PERSON>
</ROOT>

Schema Validation 是正确的,我没有问题,但随后我得到一个带有消息的InvalidOperationException

The specified type is abstract: name='MotorVehicleType', Namespace='', bei <VEHICLE xmlns=''>."}

我知道我应该指定 VEHICLE 的类型,但为什么 xml 会通过模式验证?如果 Person 元素是 WorkerPersonType,则 VEHICLE 只能是 AutobusVehicleType。这就是我在 xsd 架构中指定人员的方式。

我应该改变我的班级吗?我应该添加一些属性还是其他东西?

我不知道如何解决这个错误!

【问题讨论】:

    标签: c# xml serialization xsd


    【解决方案1】:

    三个建议:

    1. 使用xsi 作为命名空间前缀 http://www.w3.org/2001/XMLSchema-instance。这不是必需的 但是是标准的。
    2. 对路径中有空格的本地 XSD 使用以下语法: file:///C:/Users/SIGFRID/Documents/Visual%20Studio%202012/Projects/sample/ConsoleApplication1/ConsoleApplication1/MySample.xsd
    3. 使用xsi:noNamespaceSchemaLocation 而不是xsi:schemaLocation 因为你没有使用命名空间。

    这是您应用了这些建议的 XML 文件:

    <?xml version="1.0" encoding="UTF-8"?>
    <ROOT xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
          xsi:noNamespaceSchemaLocation="file:///C:/Users/SIGFRID/Documents/Visual%20Studio%202012/Projects/sample/ConsoleApplication1/ConsoleApplication1/MySample.xsd">
      <PERSON xsi:type="WorkerPersonType">
        <VEHICLE>
          <Name>VOLVO</Name>
        </VEHICLE>
      </PERSON>
    </ROOT>
    

    【讨论】:

    • 感谢您的建议。不幸的是它仍然不起作用。我认为我使用 xsd.exe 工具生成的类不正确。我读到 xsd.exe 工具有限制,并不总是生成正确的类。
    • 我在上面的 XSD 路径规范中修正了一些错误。另外,我刚刚注意到您的问题中有一条完整的错误消息-由于未格式化而丢失。在问题中编辑/修复。我注意到您在 XML 中为 PERSON 指定了非抽象类型,但您没有为 VEHICLE 这样做,XSD 将其定义为抽象类型。该错误表明必须解决此不一致问题。
    • 是的,我也这么认为。但是 XSD 中 WorkerPersonType 的定义间接包含了允许的 VEHICLE 类型。我认为也许应该改变我生成的类中的任何内容以便能够反序列化XML。但如果是不一致,为什么 xml 验证通过?
    • (1) 我不愿意在生成的代码中手动更改某些内容。 (2) 我倾向于相信 XML 验证,尤其是基于 Xerces 工具的 XML 验证是正确的。也许您遇到了 xsd.exe 的限制。您能否在不依赖 xsd.exe 正确处理@xsi:抽象类的类型驱动区分 (PERSON) 和相关的子类隐含实例化 (VEHICLE) 的情况下完成任务?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-12-19
    • 2013-10-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多