Search code examples
c#xmlserializationf#ixmlserializable

Xml serialization with custom schema and IXmlSerializable


I'm trying to serialize an object using IXmlSerializable and the XmlSchemaProviderAttribute.

The schema looks like this:

<?xml version="1.0" encoding="utf-8"?>
<xs:schema id="BuildingsSchema" targetNamespace="BuildingModelSchema"
    elementFormDefault="qualified"
    xmlns="BuildingModelSchema"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
>
    <xs:element name="buildings">
        <xs:complexType>
            <xs:sequence>
                <xs:element name="building" minOccurs="0" maxOccurs="unbounded">
                    <xs:complexType>
                        <xs:sequence>
                        ...

And the code to get the schema looks like this (as found here):

[<Literal>]
let XML_NAMESPACE                       = "BuildingModelSchema"
[<Literal>]
let XSD_SCHEMA_PATH                     = @"BuildingsSchema.xsd"

[<XmlSchemaProvider(BuildingsSchema)>]
type BuildingsStatistics() =
    interface IXmlSerializable with
    ...
    static member BuildingsSchema(xs: XmlSchemaSet) =
        let serializer = new XmlSerializer(typeof<XmlSchema>)
        let schema = (serializer.Deserialize(new XmlTextReader(XSD_SCHEMA_PATH), null)) :?> XmlSchema
        xs.XmlResolver <- new XmlUrlResolver()
        xs.Add(schema) |> ignore

        new XmlQualifiedName("buildings", XML_NAMESPACE)
    ...

Now when i try to serialize an object with the XmlSerializer i get an exception: {"PlanerModel.BuildingsStatistics.BuildingsSchema() must return a valid type name. Type 'buildings' cannot be found in the targetNamespace='BuildingModelSchema'."}

Edit:
After trying to deserialize a valid test document i get the same error message. I expect there is something wrong with the xml schema but due to the fact that this is the first time i work with xml schemata i don't seem to find the mistake.

Further testing shows that the exception is thrown on initialization of the XmlSerializer:

XmlSerializer ser = new XmlSerializer(typeof(BuildingsStatistics)); // Exception is thrown here
ser.Deserialize(...)                                                // Will not be executed

Furthermore the XmlSchema that is added in the BuildingsSchema method does not contain any element (in my case 0 elements and 14 items that are all 'empty' (no line number, position, etc.)).


Solution

  • I found the solution to my problem: I had to change the schema definition to

    <xs:complexType name="buildingsType">
        <xs:sequence>
            <xs:element name="building" type="buildingType" minOccurs="1" maxOccurs="unbounded"/>
        </xs:sequence>
    </xs:complexType>
    ...
    

    and the returned XmlQualifiedName inside the BuildingsSchema to

    new XmlQualifiedName("buildingType", XML_NAMESPACE)