XSD校验XML反序列化时报XmlSchemaValidationException提示xsi:type 'Book'无效
错误原因
报错的核心是你当前使用的XSD架构中,没有定义xsi:type引用的Book/Newspaper/Patent三种派生类型,也没有为基类LibraryAsset配置可继承的多态支持:
- Visual Studio的「创建架构」功能是基于XML实例推断结构的,它无法识别面向对象的继承关系,只会把所有实例中出现过的字段都合并到
LibraryAsset的单一类型定义中,完全没有生成派生类的相关声明,因此校验时会认为xsi:type="Book"是无效的类型值。 - 额外补充:如果C#端的
LibraryAsset抽象基类没有加[XmlInclude]特性标注派生类,就算XSD校验通过,反序列化也会失败。
解决方法
分三步处理:
1. 重写XSD架构,正确定义继承关系
把原XSD中合并的字段拆分,先定义抽象基类LibraryAsset,再通过扩展(xs:extension)定义三个派生类,修改后的XSD示例如下:
<?xml version="1.0" encoding="utf-8"?> <xs:schema xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xs="http://www.w3.org/2001/XMLSchema" attributeFormDefault="unqualified" elementFormDefault="qualified"> <!-- 定义抽象基类LibraryAsset --> <xs:complexType name="LibraryAsset" abstract="true"> <xs:sequence> <xs:element name="Id" type="xsd:unsignedInt" /> <xs:element name="Name" type="xsd:string" /> <xs:element name="YearPublished" type="xsd:unsignedShort" /> <xs:element name="PagesNumber" type="xsd:unsignedByte" /> <xs:element name="Annotation" type="xsd:string" /> <xs:element name="Price" type="xsd:unsignedByte" /> </xs:sequence> </xs:complexType> <!-- 定义派生类Book --> <xs:complexType name="Book"> <xs:complexContent> <xs:extension base="LibraryAsset"> <xs:sequence> <xs:element name="StandardNumber" type="xsd:string" /> <xs:element name="Authors"> <xs:complexType> <xs:sequence> <xs:element name="string" type="xsd:string" /> </xs:sequence> </xs:complexType> </xs:element> <xs:element name="CityPublished" type="xsd:string" /> <xs:element name="Publisher" type="xsd:string" /> <xs:element name="CopiesNumber" type="xsd:unsignedShort" /> </xs:sequence> </xs:extension> </xs:complexContent> </xs:complexType> <!-- 定义派生类Newspaper --> <xs:complexType name="Newspaper"> <xs:complexContent> <xs:extension base="LibraryAsset"> <xs:sequence> <xs:element name="StandardNumber" type="xsd:string" /> <xs:element name="CityPublished" type="xsd:string" /> <xs:element name="Publisher" type="xsd:string" /> <xs:element name="CopiesNumber" type="xsd:unsignedShort" /> <xs:element name="Issue" type="xsd:unsignedByte" /> <xs:element name="IssueDate" type="xsd:dateTime" /> </xs:sequence> </xs:extension> </xs:complexContent> </xs:complexType> <!-- 定义派生类Patent --> <xs:complexType name="Patent"> <xs:complexContent> <xs:extension base="LibraryAsset"> <xs:sequence> <xs:element name="Number" type="xsd:string" /> <xs:element name="Inventors"> <xs:complexType> <xs:sequence> <xs:element name="string" type="xsd:string" /> </xs:sequence> </xs:complexType> </xs:element> <xs:element name="Country" type="xsd:string" /> <xs:element name="ApplicationDate" type="xsd:dateTime" /> <xs:element name="IssueDate" type="xsd:dateTime" /> </xs:sequence> </xs:extension> </xs:complexContent> </xs:complexType> <!-- 定义根节点ArrayOfLibraryAsset --> <xsd:element name="ArrayOfLibraryAsset"> <xsd:complexType> <xsd:sequence> <xsd:element maxOccurs="unbounded" name="LibraryAsset" type="LibraryAsset"/> </xsd:sequence> </xsd:complexType> </xsd:element> </xs:schema>
2. 补充C#端的反序列化配置
在你的抽象基类LibraryAsset上添加XmlInclude特性,让XmlSerializer能识别派生类:
[XmlInclude(typeof(Book))] [XmlInclude(typeof(Newspaper))] [XmlInclude(typeof(Patent))] public abstract class LibraryAsset { // 原有属性定义 }
3. 可选调整验证标志
如果还存在校验问题,可以在XmlReaderSettings的ValidationFlags中添加XmlSchemaValidationFlags.ProcessInlineSchema,确保类型声明被正确处理。
内容的提问来源于stack exchange,提问作者Pavel Antropov
相关产品推荐
相关产品推荐

