func (cfg *Config) overrideWildcardType(t *xsd.ComplexType, base xsd.Type) *xsd.ComplexType { var elem xsd.Element var found bool var replaced bool Loop: for x := xsd.Type(t); xsd.Base(x) != nil; x = xsd.Base(x) { c, ok := x.(*xsd.ComplexType) if !ok { cfg.logf("warning: soap-encoded array %s extends %T %s", xsd.XMLName(x).Local, base, xsd.XMLName(base).Local) return t } for _, v := range c.Elements { if v.Wildcard { elem = v found = true break Loop } } } if !found { cfg.logf("could not override wildcard type for %s; not found in type hierarchy", t.Name.Local) return t } cfg.debugf("overriding wildcard element of %s type from %s to %s", t.Name.Local, xsd.XMLName(elem.Type).Local, xsd.XMLName(base).Local) elem.Type = base for i, v := range t.Elements { if v.Wildcard { t.Elements[i] = elem replaced = true } } if !replaced { t.Elements = append(t.Elements, elem) } return t }
// To reduce the size of the Go source generated, all intermediate types // are "squashed"; every type should be based on a Builtin or another // type that the user wants included in the Go source. func (cfg *Config) flatten1(t xsd.Type, push func(xsd.Type)) xsd.Type { switch t := t.(type) { case *xsd.SimpleType: var ( chain []xsd.Type base, builtin xsd.Type ok bool ) // TODO: handle list/union types for base = xsd.Base(t); base != nil; base = xsd.Base(base) { if builtin, ok = base.(xsd.Builtin); ok { break } chain = append(chain, base) } for _, v := range chain { if v, ok := v.(*xsd.SimpleType); ok { v.Base = builtin push(v) } } t.Base = builtin return t case *xsd.ComplexType: // We can "unpack" a struct if it is extending a simple // or built-in type and we are ignoring all of its attributes. switch t.Base.(type) { case xsd.Builtin, *xsd.SimpleType: if b, ok := t.Base.(xsd.Builtin); ok && b == xsd.AnyType { break } attributes, _ := cfg.filterFields(t) if len(attributes) == 0 { cfg.debugf("complexType %s extends simpleType %s, but all attributes are filtered. unpacking.", t.Name.Local, xsd.XMLName(t.Base)) switch b := t.Base.(type) { case xsd.Builtin: return b case *xsd.SimpleType: return cfg.flatten1(t.Base, push) } } } // We can flatten a struct field if its type does not // need additional methods for unmarshalling. for i, el := range t.Elements { el.Type = cfg.flatten1(el.Type, push) if b, ok := el.Type.(*xsd.SimpleType); ok { if !b.List && len(b.Union) == 0 { el.Type = xsd.Base(el.Type) } } t.Elements[i] = el } for i, attr := range t.Attributes { attr.Type = cfg.flatten1(attr.Type, push) if b, ok := attr.Type.(*xsd.SimpleType); ok { if !b.List && len(b.Union) == 0 { attr.Type = xsd.Base(attr.Type) } } t.Attributes[i] = attr } return t case xsd.Builtin: // There are a few built-ins that do not map directly to Go types. // for these, we will declare them in the Go source. switch t { case xsd.ENTITIES, xsd.IDREFS, xsd.NMTOKENS: push(t) case xsd.Base64Binary, xsd.HexBinary: push(t) case xsd.Date, xsd.Time, xsd.DateTime: push(t) case xsd.GDay, xsd.GMonth, xsd.GMonthDay, xsd.GYear, xsd.GYearMonth: push(t) } return t } panic(fmt.Sprintf("unexpected %T", t)) }