Home > Net >  XmlSchemaValidationException: This is an invalid xsi:type 'Book' when trying to deserializ
XmlSchemaValidationException: This is an invalid xsi:type 'Book' when trying to deserializ

Time:11-22

I have an xml with an array of LibraryAssets, those are Books, Newspapers and Patents, and LibraryAsset is the abstract class they derive from. I created an xsd schema based on that xml using visual studio's Create schema. But when I try to deserialize the xml validating that it matches the schema I get the following error:

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)

My xsd schema:

<?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>

The Xml file:

<?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 deserialization:

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>;

CodePudding user response:

So, your schema generator has a limitation that it ignores xsi:type attributes. That's not a great surprise, it's hard to know what it would do with them.

You obviously know something that the tool doesn't ("LibraryAssets are Books, Newspapers and Patents, and LibraryAsset is the abstract class they derive from") and it's normal practice that when you generate a schema, what you get is only a first cut, and you're expected to edit it to take account of your knowledge of the semantics of the application domain.

CodePudding user response:

The solution is much more simple then I thought it would be.

So, basically, I just had to declare each type (Book, Newspaper, Patent being extensions of abstract LibraryAsset). The final solution XSD looks like this:

<?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>
  • Related