使用自定义模式和IXmlSerializable进行Xml序列化

本文关键字:进行 Xml 序列化 IXmlSerializable 自定义 模式 | 更新日期: 2023-09-27 18:02:42

我正在尝试使用IXmlSerializableXmlSchemaProviderAttribute序列化对象。

模式如下所示:

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

获取模式的代码如下所示:

[<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)
    ...

现在当我尝试用XmlSerializer序列化一个对象时,我得到一个异常:{"PlanerModel.BuildingsStatistics.BuildingsSchema()必须返回一个有效的类型名。在targetNamespace='BuildingModelSchema'中找不到类型'buildings'。"}

编辑:


在尝试反序列化有效的测试文档后,我得到相同的错误信息。我预计xml模式有问题,但由于这是我第一次使用xml模式,我似乎没有发现错误。

进一步的测试表明,在初始化XmlSerializer时抛出异常:

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

此外,在BuildingsSchema方法中添加的XmlSchema不包含任何元素(在我的例子中,0个元素和14个项目都是'空'(没有行号,位置等))。

使用自定义模式和IXmlSerializable进行Xml序列化

我找到了问题的解决方案:我必须将模式定义更改为

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

BuildingsSchema中返回的XmlQualifiedName

new XmlQualifiedName("buildingType", XML_NAMESPACE)