简体   繁体   中英

How to Generate Strongly Typed .NET Request Object from XSD in .NET

I've been given a number of XSD files - they are HUGE - for an insurance pricing engine, so as you can imagine, contain lots of nested complex types. Person, Address, Vehicles, Car Alarm, Speeding Convictions etc etc. Here's a subset containing a single complex type:

<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified">

    <xs:complexType name="Vehicle">
        <xs:choice maxOccurs="unbounded">
            <xs:element name="ABICode" type="ABICode" minOccurs="0"/>
            <xs:element name="ABSBrakes" type="ABSBrakes" minOccurs="0"/>
            <xs:element name="AgedOver" type="AgedOver" minOccurs="0"/>
            <xs:element name="AlarmSecurityFitted" type="AlarmSecurityFitted" minOccurs="0"/>
            <xs:element name="AlarmSecurityMake" type="AlarmSecurityMake" minOccurs="0"/>
            <xs:element name="AudioValue" type="AudioValue" minOccurs="0"/>
            <xs:element name="CarPhoneValue" type="CarPhoneValue" minOccurs="0"/>
            <xs:element name="Colour" type="Colour" minOccurs="0"/>
            <xs:element name="CountryOfManufacture" type="CountryOfManufacture" minOccurs="0"/>
            <xs:element name="CoverType" type="CoverType" minOccurs="0"/>
            <xs:element name="CurrentMileage" type="CurrentMileage" minOccurs="0"/>
            <xs:element name="Doors" type="Doors" minOccurs="0"/>
            <xs:element name="EngineSize" type="EngineSize" minOccurs="0"/>
            <xs:element name="EstimatedValue" type="EstimatedValue" minOccurs="0"/>
            <xs:element name="Finish" type="Finish" minOccurs="0"/>
            <xs:element name="FuelType" type="FuelType" minOccurs="0"/>
            <xs:element name="HasSecurity" type="HasSecurity" minOccurs="0"/>
            <xs:element name="ImmobSecurityFitted" type="ImmobSecurityFitted" minOccurs="0"/>
            <xs:element name="ImmobSecurityMake" type="ImmobSecurityMake" minOccurs="0"/>
            <xs:element name="Keeper" type="Keeper" minOccurs="0"/>
            <xs:element name="Lhd" type="Lhd" minOccurs="0"/>
            <xs:element name="Modified" type="Modified" minOccurs="0"/>
            <xs:element name="NCBCountry" type="NCBCountry" minOccurs="0"/>
            <xs:element name="NCBProtected" type="NCBProtected" minOccurs="0"/>
            <xs:element name="NCBType" type="NCBType" minOccurs="0"/>
            <xs:element name="NCBYears" type="NCBYears" minOccurs="0"/>
            <xs:element name="NightLocation" type="NightLocation" minOccurs="0"/>
            <xs:element name="Owner" type="Owner" minOccurs="0"/>
            <xs:element name="OvernightPostCode" type="OvernightPostCode" minOccurs="0"/>
            <xs:element name="PermittedDrivers" type="PermittedDrivers" minOccurs="0"/>
            <xs:element name="PricePaid" type="PricePaid" minOccurs="0"/>
            <xs:element name="PurchaseDate" type="PurchaseDate" minOccurs="0"/>
            <xs:element name="Registration" type="Registration" minOccurs="0"/>
            <xs:element name="Seats" type="Seats" minOccurs="0"/>
            <xs:element name="TrackerSecurityFitted" type="TrackerSecurityFitted" minOccurs="0"/>
            <xs:element name="TrackerSecurityMake" type="TrackerSecurityMake" minOccurs="0"/>
            <xs:element name="Transmission" type="Transmission" minOccurs="0"/>
            <xs:element name="Type" type="Type" minOccurs="0"/>
            <xs:element name="Windscreen" type="Windscreen" minOccurs="0"/>
            <xs:element name="YearManufacture" type="YearManufacture" minOccurs="0"/>
            <xs:element name="Modification" type="Modification" minOccurs="0" maxOccurs="5"/>
        </xs:choice>
    </xs:complexType>
</xs:schema>

I've successfully used xsd.exe and xsd2code to generate classes based on the schema definiitions, however, the classes that have been produced are not strongly typed, and contain arrays of Objects such as this:

  [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Xml", "4.6.1064.2")]
[System.SerializableAttribute()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
public partial class Vehicle
{

    private object[] _items;

    private ItemsChoiceType4[] _itemsElementName;

    [System.Xml.Serialization.XmlElementAttribute("ABICode", typeof(string))]
    [System.Xml.Serialization.XmlElementAttribute("ABSBrakes", typeof(ABSBrakes))]
    [System.Xml.Serialization.XmlElementAttribute("AgedOver", typeof(string))]
    [System.Xml.Serialization.XmlElementAttribute("AlarmSecurityFitted", typeof(AlarmSecurityFitted))]
    [System.Xml.Serialization.XmlElementAttribute("AlarmSecurityMake", typeof(AlarmSecurityMake))]
    [System.Xml.Serialization.XmlElementAttribute("AudioValue", typeof(string))]
    [System.Xml.Serialization.XmlElementAttribute("CarPhoneValue", typeof(string))]
    [System.Xml.Serialization.XmlElementAttribute("Colour", typeof(Colour))]
    [System.Xml.Serialization.XmlElementAttribute("CountryOfManufacture", typeof(CountryOfManufacture))]
    [System.Xml.Serialization.XmlElementAttribute("CoverType", typeof(CoverType))]
    [System.Xml.Serialization.XmlElementAttribute("CurrentMileage", typeof(string))]
    [System.Xml.Serialization.XmlElementAttribute("Doors", typeof(string))]
    [System.Xml.Serialization.XmlElementAttribute("EngineSize", typeof(string))]
    [System.Xml.Serialization.XmlElementAttribute("EstimatedValue", typeof(string))]
    [System.Xml.Serialization.XmlElementAttribute("Finish", typeof(Finish))]
    [System.Xml.Serialization.XmlElementAttribute("FuelType", typeof(FuelType))]
    [System.Xml.Serialization.XmlElementAttribute("HasSecurity", typeof(HasSecurity))]
    [System.Xml.Serialization.XmlElementAttribute("ImmobSecurityFitted", typeof(ImmobSecurityFitted))]
    [System.Xml.Serialization.XmlElementAttribute("ImmobSecurityMake", typeof(ImmobSecurityMake))]
    [System.Xml.Serialization.XmlElementAttribute("Keeper", typeof(Keeper))]
    [System.Xml.Serialization.XmlElementAttribute("Lhd", typeof(Lhd))]
    [System.Xml.Serialization.XmlElementAttribute("Modification", typeof(Modification))]
    [System.Xml.Serialization.XmlElementAttribute("Modified", typeof(Modified))]
    [System.Xml.Serialization.XmlElementAttribute("NCBCountry", typeof(NCBCountry))]
    [System.Xml.Serialization.XmlElementAttribute("NCBProtected", typeof(NCBProtected))]
    [System.Xml.Serialization.XmlElementAttribute("NCBType", typeof(NCBType))]
    [System.Xml.Serialization.XmlElementAttribute("NCBYears", typeof(string))]
    [System.Xml.Serialization.XmlElementAttribute("NightLocation", typeof(NightLocation))]
    [System.Xml.Serialization.XmlElementAttribute("OvernightPostCode", typeof(string))]
    [System.Xml.Serialization.XmlElementAttribute("Owner", typeof(Owner))]
    [System.Xml.Serialization.XmlElementAttribute("PermittedDrivers", typeof(PermittedDrivers))]
    [System.Xml.Serialization.XmlElementAttribute("PricePaid", typeof(string))]
    [System.Xml.Serialization.XmlElementAttribute("PurchaseDate", typeof(string))]
    [System.Xml.Serialization.XmlElementAttribute("Registration", typeof(string))]
    [System.Xml.Serialization.XmlElementAttribute("Seats", typeof(string))]
    [System.Xml.Serialization.XmlElementAttribute("TrackerSecurityFitted", typeof(TrackerSecurityFitted))]
    [System.Xml.Serialization.XmlElementAttribute("TrackerSecurityMake", typeof(TrackerSecurityMake))]
    [System.Xml.Serialization.XmlElementAttribute("Transmission", typeof(Transmission))]
    [System.Xml.Serialization.XmlElementAttribute("Type", typeof(string))]
    [System.Xml.Serialization.XmlElementAttribute("Windscreen", typeof(Windscreen))]
    [System.Xml.Serialization.XmlElementAttribute("YearManufacture", typeof(string))]
    [System.Xml.Serialization.XmlChoiceIdentifierAttribute("ItemsElementName")]
    public object[] Items
    {
        get
        {
            return this._items;
        }
        set
        {
            this._items = value;
        }
    }

Ideally I would like the Vehicle class to have a number of properties which are instances of other classes so that I can use automapper to map from my domain model to the request object, serialize to XML and send the request.

But the way these types have been created, I have lost any information about the structure of the request object I need to build. Everything will need to be mapped explicitly property by property. And yet despite fiddling with all the settings in xsd2code and switches of xsd.exe I can't seem to get it to generate anything like what I want.

Is there a way to do what I want, or do I need to change my approach?

I've done similar work and used xsd.exe, but in this case I believe the problem is the way the schema is laid out. The Vehicle node is an unbounded list of elements that could be any one of 40 different types of objects (ABSBrakes, AgedOver ... YearManufacture). The creator of the schema hasn't left you any options other than to map them property by property.

I realize it's not what you want to hear, but when you come across windscreen data, create a Windscreen object and add it to Vehicle.Items and continue for each property. When you serialize this, it should create valid XML matching the given schema.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM