John Smith
John Smith

Reputation: 343

Use inheritance in XML deserialisation

I'm trying to deserialize with inheritance.

For example, I have a class for opensearch

Shortly, the XSD is like this:

<?xml version="1.0" encoding="utf-8"?>
<xs:schema attributeFormDefault="unqualified" elementFormDefault="qualified" targetNamespace="http://a9.com/-/spec/opensearch/1.1/" xmlns:xs="http://www.w3.org/2001/XMLSchema">
  <xs:element name="OpenSearchDescription">
    <xs:complexType>
      <xs:sequence>
        <xs:element name="ShortName" type="xs:string" />
      </xs:sequence>
    </xs:complexType>
  </xs:element>
</xs:schema>

Mozilla impements this but they use their own scheme.

so they have:

<?xml version="1.0" encoding="Windows-1252"?>
<xs:schema xmlns:os="http://a9.com/-/spec/opensearch/1.1/" attributeFormDefault="unqualified" elementFormDefault="qualified" targetNamespace="http://www.mozilla.org/2006/browser/search/" xmlns:xs="http://www.w3.org/2001/XMLSchema">
  <xs:import namespace="http://a9.com/-/spec/opensearch/1.1/" />
  <xs:element name="SearchPlugin">
    <xs:complexType>
      <xs:sequence>
        <xs:element ref="os:ShortName" />
      </xs:sequence>
    </xs:complexType>
  </xs:element>
</xs:schema>

For opensearch I have a class like

[SerializableAttribute]
[XmlRoot(Namespace = "http://a9.com/-/spec/opensearch/1.1/", IsNullable = false, ElementName = "OpenSearchDescription")]
public class OpenSearch
{
    public string ShortName { get; set; }
}

This works fine when I try to deserialise an xml...

For my mozilla implementation I just want something like this:

[System.SerializableAttribute]
[XmlRoot(Namespace = "http://www.mozilla.org/2006/browser/search/", IsNullable = false, ElementName = "SearchPlugin")]
public class SearchPlugin
{
    public OpenSearch OpenSearch { get; set; }
}

however, whenever I try to deserialise a SearchPlugin object, the OpenSearch object is just NULL.

How am I suppose to do this? I tried to create an example for myself by generating code with xsd.exe, however I also keep getting errors when I try to generate code for the SearchPlugin.xsd, so that did not help...

Upvotes: 1

Views: 314

Answers (1)

Petru Gardea
Petru Gardea

Reputation: 21638

I would start with the XML you're trying to deserialize, get the XSD files out of that XML, tweak the XSDs if needed to make sure they're valid, then use the xsd.exe to generate the classes. By looking at the generated classes, you'll see what's missing.

Someone really used to xsd.exe's ways would immediately point out that the OpenSearch property of the SearchPlugin class has no XmlElementAttribute, something like

[System.Xml.Serialization.XmlElementAttribute(Namespace="http://a9.com/-/spec/opensearch/1.1/")]

I believe that's the reason why you're getting null. Below is just how I would troubleshoot...

Starting with the XML; based on your schemas and class, I would assume that you're expecting something like below:

<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<!-- Sample XML generated by QTAssistant (http://www.paschidev.com) -->
<SearchPlugin xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:os="http://a9.com/-/spec/opensearch/1.1/" xmlns="http://www.mozilla.org/2006/browser/search/">
    <os:OpenSearchDescription>
        <os:ShortName>ShortName1</os:ShortName>
    </os:OpenSearchDescription>
</SearchPlugin>

The XSD diagram would like this:

Mozilla SearchPlugin diagram

Which means, you can use these XSDs:

<?xml version="1.0" encoding="Windows-1252"?>
<xs:schema xmlns:os="http://a9.com/-/spec/opensearch/1.1/" attributeFormDefault="unqualified" elementFormDefault="qualified" targetNamespace="http://www.mozilla.org/2006/browser/search/" xmlns:xs="http://www.w3.org/2001/XMLSchema">
    <xs:import namespace="http://a9.com/-/spec/opensearch/1.1/" schemaLocation="OpenSearch.xsd"/>
    <xs:element name="SearchPlugin">
        <xs:complexType>
            <xs:sequence>
                <xs:element ref="os:OpenSearchDescription"/>
            </xs:sequence>
        </xs:complexType>
    </xs:element>
</xs:schema>

OpenSearch.xsd being the one you've posted.

If you run xsd.exe, you'll get this output:

C:\.....>xsd MozillaOpenSearch.xsd OpenSearch.xsd /classes
Microsoft (R) Xml Schemas/DataTypes support utility
[Microsoft (R) .NET Framework, Version 4.0.30319.1]
Copyright (C) Microsoft Corporation. All rights reserved.
Writing file 'C:\....\OpenSearch.cs'.

The generated class:

using System.Xml.Serialization;

// 
// This source code was auto-generated by xsd, Version=4.0.30319.1.
// 


/// <remarks/>
[System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.0.30319.1")]
[System.SerializableAttribute()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType=true,     Namespace="http://www.mozilla.org/2006/browser/search/")]
[System.Xml.Serialization.XmlRootAttribute(Namespace="http://www.mozilla.org/2006/browser/search/", IsNullable=false)]
public partial class SearchPlugin {

    private OpenSearchDescription openSearchDescriptionField;

    /// <remarks/>
    [System.Xml.Serialization.XmlElementAttribute(Namespace="http://a9.com/-/spec/opensearch/1.1/")]
    public OpenSearchDescription OpenSearchDescription {
        get {
            return this.openSearchDescriptionField;
        }
        set {
            this.openSearchDescriptionField = value;
        }
    }
}

/// <remarks/>
[System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.0.30319.1")]
[System.SerializableAttribute()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType=true, Namespace="http://a9.com/-/spec/opensearch/1.1/")]
[System.Xml.Serialization.XmlRootAttribute(Namespace="http://a9.com/-/spec/opensearch/1.1/", IsNullable=false)]
public partial class OpenSearchDescription {

    private string shortNameField;

    /// <remarks/>
    public string ShortName {
        get {
            return this.shortNameField;
        }
        set {
            this.shortNameField = value;
        }
    }
}

Upvotes: 4

Related Questions