go-xml icon indicating copy to clipboard operation
go-xml copied to clipboard

xsdgen on tableau api 3.6 xsd fails to generate

Open jaby opened this issue 5 years ago • 2 comments

When trying to generate the schema structures for the Tableau 3.6. api, the generation is invalid.

Full xsd is available here: https://help.tableau.com/samples/en-us/rest_api/ts-api_3_6.xsd

More specifically the Lastday in this monthDay attribute is generated as 'type string', while it should have been 'type LastDay string'

    <xs:complexType name="intervalType">
        <xs:attribute name="minutes">
            <xs:simpleType>
                <xs:restriction base="xs:nonNegativeInteger">
                    <xs:enumeration value="15" />
                    <xs:enumeration value="30" />
                </xs:restriction>
            </xs:simpleType>
        </xs:attribute>
        <xs:attribute name="hours">
            <xs:simpleType>
                <xs:restriction base="xs:nonNegativeInteger">
                    <xs:enumeration value="1" />
                    <xs:enumeration value="2" />
                    <xs:enumeration value="4" />
                    <xs:enumeration value="6" />
                    <xs:enumeration value="8" />
                    <xs:enumeration value="12" />
                </xs:restriction>
            </xs:simpleType>
        </xs:attribute>
        <xs:attribute name="weekDay" >
            <xs:simpleType>
                <xs:restriction base="xs:string">
                    <xs:enumeration value="Monday" />
                    <xs:enumeration value="Tuesday" />
                    <xs:enumeration value="Wednesday" />
                    <xs:enumeration value="Thursday" />
                    <xs:enumeration value="Friday" />
                    <xs:enumeration value="Saturday" />
                    <xs:enumeration value="Sunday" />
                </xs:restriction>
            </xs:simpleType>
        </xs:attribute>
        <xs:attribute name="monthDay" >
            <xs:simpleType>
                <xs:union>
                    <xs:simpleType>
                        <xs:restriction base="xs:integer">
                            <xs:minInclusive value="1" />
                            <xs:maxInclusive value="31" />
                        </xs:restriction>
                    </xs:simpleType>
                    <xs:simpleType>
                        <xs:restriction base="xs:string">
                            <xs:enumeration value="LastDay" />
                        </xs:restriction>
                    </xs:simpleType>
                </xs:union>
            </xs:simpleType>
        </xs:attribute>
    </xs:complexType>

I suspect a problem with the union combining 2 different datatypes 'xs:integer' and 'xs:string', but I have not investigated in detail. Other union combining 'xs:integer' with 'xs:integer' works fine.

Currently using this workaround, as there seems to be only 1 xsdSimpleType with a blanc name:

func main() {
	var cfg xsdgen.Config

	cfg.Option(
		xsdgen.IgnoreAttributes("href", "offset"),
		xsdgen.Replace(`[._ \s-]`, ""),
		xsdgen.PackageName("ws"),
		xsdgen.HandleSOAPArrayType(),
		xsdgen.SOAPArrayAsSlice(),
		xsdgen.UseFieldNames(),

		xsdgen.ProcessTypes(func(s xsd.Schema, t xsd.Type) xsd.Type {
			switch t.(type) {
			case *xsd.SimpleType:
				// workaround for the invalid generation of LastDay type,
				st := t.(*xsd.SimpleType)
				if st.Name.Local == "" {
					st.Name.Local = "LastDay"
				}
			}
			return t
		}),
	)
	if err := cfg.GenCLI(os.Args[1:]...); err != nil {
		log.Fatal(err)
	}
}

jaby avatar Mar 05 '20 11:03 jaby

I haven't looked to deeply into this, but I looked at the output from an xsdgen run. Looking at the schema, I would expect this

    type MonthDay string

which is in the output. But this

    // May be one of LastDay
    type  string

shouldn't be there at all. That's a bug. It shouldn't be type LastDay string either, "LastDay" is a potential value for the type, not the type itself. The type itself is anonymous, so if anything it should be

    type AnonX string

However, there should be some passes that remove anonymous types that can just be put directly in struct definitions, so that shouldn't exist either. The xsdgen package does not handle union types well. In an ideal world, I'd like to have something like this:

    type MonthDay interface {
      xsdUnionMonthDay()
    }
    
    // range 1-31
    type MonthDay1 int
    func (MonthDay1) xsdUnionMonthDay() {}
    
    // may be one of LastDay
    type MonthDay2 string
    func (MonthDay1) xsdUnionMonthDay() {}

Even that is a little ugly.

droyo avatar Mar 21 '20 02:03 droyo

I also saw this issue when generating code from the ONIX 3.0 spec: https://www.editeur.org/93/Release-3.0-Downloads/

Most types were generated as type string instead of their (existing but not used) more complex types and a lot of anonymous types were left unreferenced. I went through and manually repaired about 1k worth of references to use their more specific type but I'm certain this could be done in the tool if it was clear on how it was supposed to happen.

nikolawannabe avatar May 05 '22 23:05 nikolawannabe