go-xml
go-xml copied to clipboard
xsdgen on tableau api 3.6 xsd fails to generate
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)
}
}
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.
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.