mganss / XmlSchemaClassGenerator

Generate C# classes from XML Schema files
Apache License 2.0
603 stars 180 forks source link

Question: How do I tackle complex types? #499

Open digitaldias opened 7 months ago

digitaldias commented 7 months ago

Apologies for posting questions here, but I cannot find any answers on how to solve my issue.

I am in a project where our .Net team will read and write types to the same MongoDB as another team on Java/Kotlin. The issue I am having is that they are storing Dates and Times as strings (our DateOnly and TimeOnly types), whilst the timestamps (DateTimeOffsets) are ok and compatible.

What I need to do is to generate C# classes from the same XSD files as theirs, and the specific declaration of date is as such:

    <xsd:complexType name="DateType">
        <xsd:sequence>
            <xsd:element name="DateCode" minOccurs="0">
                <xsd:annotation>
                    <xsd:documentation>Kode for tidsangivelse</xsd:documentation>
                </xsd:annotation>
                <xsd:simpleType>
                    <xsd:restriction base="xsd:string"/>
                </xsd:simpleType>
            </xsd:element>
            <xsd:element name="Date" type="xsd:date">
                <xsd:annotation>
                    <xsd:documentation>Dato (YYYY-MM-DD)</xsd:documentation>
                </xsd:annotation>
            </xsd:element>
            <xsd:element name="Time" type="xsd:time" minOccurs="0">
                <xsd:annotation>
                    <xsd:documentation>Klokkeslett (HH:MM:SS)</xsd:documentation>
                </xsd:annotation>
            </xsd:element>
        </xsd:sequence>
    </xsd:complexType>

I am using the XmlSchemaClassGenerator Nuget package, and attempting to map these specific types to string (the xsd:date and xsd:time), using a TypeVisitor that calls this method:

    static readonly Dictionary<string, Type> _typeMaps = new()
    {
            {"Date", typeof(DateOnly)},
            {"Time", typeof(TimeOnly)},
            { "DateTimeType", typeof(DateTimeOffset)}
    };

    private void PerformTypeVisit(CodeTypeDeclaration declaration, TypeModel model)
    {
        if (_typeMaps.Keys.Any(k => k == model.Name))
        {
            declaration.BaseTypes.Clear();
            declaration.BaseTypes.Add(_typeMaps[model.Name]);
        }
    }

This, of course, isn't working for me, or I wouldn't be posting the question here. Can someone help me with this? The number of classes to be generated is fairly big, around 200 of them, since we're dealing with ALL Xsds that declare orders/invoices in various standards for my country. I know that this tool does not have type mapping, but can it still be solved in some smart way?

Ideally, I would be able to provide a type map where I'd map for example xs:time and xs:date to C# string .

digitaldias commented 7 months ago

Answering myself now:

I ALMOST have it I think with type and member visitors, but I need some guidance on how to use them properly. The tests in this repo only show THAT they're called, but not how I can force a remap.

mganss commented 7 months ago

I don't think XmlSerializer supports DateOnly/TimeOnly yet, see #310. What prevents you from using DateTime?

digitaldias commented 7 months ago

I don't think XmlSerializer supports DateOnly/TimeOnly yet, see #310. What prevents you from using DateTime?

I have a team of Java developers who have already decided to store all dates in strings, preventing me from using DateTime. I would destroy their way of reading dates.

I have this code 99% done now and only need to figure out how to add my own "using" statements from a type visitor, as one of the things I am adding is a MongoDB "KnownTypes" for polymorphic objects. The Attribute is in place, but it would be awesome if I could also add the using MongoDB.Bson statement :)