XmlSchemaValidationException:这是一个无效的 xsi:type 'Book' 尝试反序列化使用 XSD 架构验证它的 XML 时
Posted
技术标签:
【中文标题】XmlSchemaValidationException:这是一个无效的 xsi:type \'Book\' 尝试反序列化使用 XSD 架构验证它的 XML 时【英文标题】:XmlSchemaValidationException: This is an invalid xsi:type 'Book' when trying to deserialize an XML validating it with an XSD schemaXmlSchemaValidationException:这是一个无效的 xsi:type 'Book' 尝试反序列化使用 XSD 架构验证它的 XML 时 【发布时间】:2021-12-30 19:07:56 【问题描述】:我有一个包含 LibraryAssets 数组的 xml,它们是书籍、报纸和专利,而 LibraryAsset 是它们派生的抽象类。 我使用 Visual Studio 的 Create 架构基于该 xml 创建了一个 xsd 架构。 但是当我尝试反序列化验证它是否与架构匹配的 xml 时,我收到以下错误:
System.InvalidOperationException : There is an error in XML document (3, 4).
----> System.Xml.Schema.XmlSchemaValidationException : This is an invalid xsi:type 'Book'.
at System.Xml.Serialization.XmlSerializer.Deserialize(XmlReader xmlReader, String encodingStyle, XmlDeserializationEvents events)
我的 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">
<xsd:element name="ArrayOfLibraryAsset">
<xsd:complexType>
<xsd:sequence>
<xsd:element maxOccurs="unbounded" name="LibraryAsset">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="Id" type="xsd:unsignedInt" />
<xsd:element name="Name" type="xsd:string" />
<xsd:element name="YearPublished" type="xsd:unsignedShort" />
<xsd:element name="PagesNumber" type="xsd:unsignedByte" />
<xsd:element name="Annotation" type="xsd:string" />
<xsd:element name="Price" type="xsd:unsignedByte" />
<xsd:element minOccurs="0" name="Number" type="xsd:string" />
<xsd:element minOccurs="0" name="Inventors">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="string" type="xsd:string" />
</xsd:sequence>
</xsd:complexType>
</xsd:element>
<xsd:element minOccurs="0" name="Country" type="xsd:string" />
<xsd:element minOccurs="0" name="ApplicationDate" type="xsd:dateTime" />
<xsd:element minOccurs="0" name="StandardNumber" type="xsd:string" />
<xsd:element minOccurs="0" name="Authors">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="string" type="xsd:string" />
</xsd:sequence>
</xsd:complexType>
</xsd:element>
<xsd:element minOccurs="0" name="CityPublished" type="xsd:string" />
<xsd:element minOccurs="0" name="Publisher" type="xsd:string" />
<xsd:element minOccurs="0" name="CopiesNumber" type="xsd:unsignedShort" />
<xsd:element minOccurs="0" name="Issue" type="xsd:unsignedByte" />
<xsd:element minOccurs="0" name="IssueDate" type="xsd:dateTime" />
</xsd:sequence>
</xsd:complexType>
</xsd:element>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
</xs:schema>
Xml 文件:
<?xml version="1.0"?>
<ArrayOfLibraryAsset xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<LibraryAsset xsi:type="Book">
<Id>62915385</Id>
<Name>Unspecified</Name>
<YearPublished>2000</YearPublished>
<PagesNumber>200</PagesNumber>
<Annotation>No annotation.</Annotation>
<Price>50</Price>
<StandardNumber>000-0-00-000000-0</StandardNumber>
<Authors>
<string>Author</string>
</Authors>
<CityPublished>Unspecified</CityPublished>
<Publisher>Unspecified</Publisher>
<CopiesNumber>300</CopiesNumber>
</LibraryAsset>
<LibraryAsset xsi:type="Newspaper">
<Id>57188600</Id>
<Name>Unspecified</Name>
<YearPublished>2021</YearPublished>
<PagesNumber>25</PagesNumber>
<Annotation>No annotation.</Annotation>
<Price>5</Price>
<StandardNumber>0000-0000</StandardNumber>
<CityPublished>Unspecified</CityPublished>
<Publisher>Unspecified</Publisher>
<CopiesNumber>1500</CopiesNumber>
<Issue>10</Issue>
<IssueDate>2021-11-19T00:00:00+04:00</IssueDate>
</LibraryAsset>
<LibraryAsset xsi:type="Patent">
<Id>14464371</Id>
<Name>Unspecified</Name>
<YearPublished>2021</YearPublished>
<PagesNumber>50</PagesNumber>
<Annotation>No annotation.</Annotation>
<Price>10</Price>
<Number>X0000000</Number>
<Inventors>
<string>Inventor</string>
</Inventors>
<Country>Unspecified</Country>
<ApplicationDate>2021-11-19T00:00:00+04:00</ApplicationDate>
<IssueDate>2021-11-18T19:34:16.5902406+04:00</IssueDate>
</LibraryAsset>
</ArrayOfLibraryAsset>
Xml 反序列化:
var schemas = new XmlSchemaSet();
schemas.Add(null, shemaFilePath);
Exception exception = null;
var settings = new XmlReaderSettings
Schemas = schemas,
ValidationType = ValidationType.Schema,
ValidationFlags =
XmlSchemaValidationFlags.ProcessIdentityConstraints |
XmlSchemaValidationFlags.ReportValidationWarnings
;
settings.ValidationEventHandler += delegate (object sender, ValidationEventArgs args)
if (args.Severity == XmlSeverityType.Warning)
_log.Warning(args.Message);
else
exception ??= args.Exception;
_log.Error(exception);
throw exception;
;
using var fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read);
using var xmlReader = XmlReader.Create(fileStream, settings);
var xmlSerializer = new XmlSerializer(typeof(List<T>));
data = xmlSerializer.Deserialize(xmlReader) as List<T>;
【问题讨论】:
你说你有一个抽象的抽象类型 libraryassets 是抽象的。你的 XSD 告诉了一些不同的东西,它只是它有一个复杂的类型 LibraryAssets,它不知道这本书是从哪里派生的? @Aldert 那我该怎么说呢?我项目中的 LibraryAsset 类有一个标签 [XmlInclude(typeof(Book))]。如果我也应该在 xsd 中添加一些东西,那会是什么? 【参考方案1】:解决方案比我想象的要简单得多。
所以,基本上,我只需要声明每种类型(书籍、报纸、专利是抽象 LibraryAsset 的扩展)。最终解决方案 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">
<xs:element name="LibraryAsset" type="LibraryAsset" abstract="true"/>
<xs:element name="Book" type="Book"/>
<xs:element name="Newspaper" type="Newspaper"/>
<xs:element name="Patent" type="Patent"/>
<xsd:complexType name="LibraryAsset" abstract="true">
<xsd:sequence>
<xsd:element name="Id" type="xsd:int" />
<xsd:element name="Name" type="xsd:string" />
<xsd:element name="YearPublished" type="xsd:int" />
<xsd:element name="PagesNumber" type="xsd:int" />
<xsd:element name="Annotation" type="xsd:string" />
<xsd:element name="Price" type="xsd:int" />
<xsd:element minOccurs="0" name="Number" type="xsd:string" />
<xsd:element minOccurs="0" name="Inventors">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="string" type="xsd:string" />
</xsd:sequence>
</xsd:complexType>
</xsd:element>
<xsd:element minOccurs="0" name="Country" type="xsd:string" />
<xsd:element minOccurs="0" name="ApplicationDate" type="xsd:dateTime" />
<xsd:element minOccurs="0" name="StandardNumber" type="xsd:string" />
<xsd:element minOccurs="0" name="Authors">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="string" type="xsd:string" />
</xsd:sequence>
</xsd:complexType>
</xsd:element>
<xsd:element minOccurs="0" name="CityPublished" type="xsd:string" />
<xsd:element minOccurs="0" name="Publisher" type="xsd:string" />
<xsd:element minOccurs="0" name="CopiesNumber" type="xsd:int" />
<xsd:element minOccurs="0" name="Issue" type="xsd:int" />
<xsd:element minOccurs="0" name="IssueDate" type="xsd:dateTime" />
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="Book">
<xsd:complexContent>
<xsd:extension base="LibraryAsset">
</xsd:extension>
</xsd:complexContent>
</xsd:complexType>
<xsd:complexType name="Newspaper">
<xsd:complexContent>
<xsd:extension base="LibraryAsset">
</xsd:extension>
</xsd:complexContent>
</xsd:complexType>
<xsd:complexType name="Patent">
<xsd:complexContent>
<xsd:extension base="LibraryAsset">
</xsd:extension>
</xsd:complexContent>
</xsd:complexType>
<xsd:element name="ArrayOfLibraryAsset">
<xsd:complexType>
<xsd:sequence>
<xsd:element minOccurs="0" maxOccurs="unbounded" name="LibraryAsset">
</xsd:element>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
</xs:schema>
【讨论】:
【参考方案2】:因此,您的模式生成器有一个限制,即忽略 xsi:type
属性。这并不奇怪,很难知道它会对它们做什么。
您显然知道该工具不知道的一些东西(“LibraryAssets 是书籍、报纸和专利,LibraryAsset 是它们派生自的抽象类”),并且通常的做法是,当您生成架构时,您得到的只是第一次剪辑,您应该根据您对应用程序域语义的了解对其进行编辑。
【讨论】:
@Michael_Kay 我正在努力寻找在这种情况下该怎么做,但我仍然没有成功。也许你可以给我一个提示,告诉我如何让它知道我的期望?我试图命名元素 Book 而不是 LibraryAsset 并向其添加以上是关于XmlSchemaValidationException:这是一个无效的 xsi:type 'Book' 尝试反序列化使用 XSD 架构验证它的 XML 时的主要内容,如果未能解决你的问题,请参考以下文章