// Return the identifier for non-builtin types, and the Go expression // mapped to the built-in type. func (cfg *Config) expr(t xsd.Type) (ast.Expr, error) { if t, ok := t.(xsd.Builtin); ok { ex := builtinExpr(t) if ex == nil { return nil, fmt.Errorf("Unknown built-in type %q", t.Name().Local) } return ex, nil } return ast.NewIdent(cfg.typeName(xsd.XMLName(t))), nil }
// 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)) }