// O(n²) is OK since you'll never see more than ~40 attributes... // right? func mergeAttributes(src, base *xsd.ComplexType) []xsd.Attribute { Loop: for _, baseattr := range base.Attributes { for _, srcattr := range src.Attributes { if srcattr.Name == baseattr.Name { continue Loop } } src.Attributes = append(src.Attributes, baseattr) } return src.Attributes }
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 }
func (cfg *Config) genComplexType(t *xsd.ComplexType) ([]spec, error) { var result []spec var fields []ast.Expr if t.Extends { base, err := cfg.expr(t.Base) if err != nil { return nil, fmt.Errorf("%s base type %s: %v", t.Name.Local, xsd.XMLName(t.Base).Local, err) } switch b := t.Base.(type) { case *xsd.SimpleType: cfg.debugf("complexType %[1]s extends simpleType %[2]s. Naming"+ " the chardata struct field after %[2]s", t.Name.Local, b.Name.Local) fields = append(fields, base, base, gen.String(`xml:",chardata"`)) case xsd.Builtin: if b == xsd.AnyType { // extending anyType doesn't really make sense, but // we can just ignore it. cfg.debugf("complexType %s: don't know how to extend anyType, ignoring", t.Name.Local) break } // Name the field after the xsd type name. cfg.debugf("complexType %[1]s extends %[2]s, naming chardata struct field %[2]s", t.Name.Local, b) fields = append(fields, ast.NewIdent(b.String()), base, gen.String(`xml:",chardata"`)) case *xsd.ComplexType: // Use struct embedding when extending a complex type cfg.debugf("complexType %s extends %s, embedding struct", t.Name.Local, b.Name.Local) fields = append(fields, nil, base, nil) } } else { // When restricting a complex type, all attributes are "inherited" from // the base type (but not elements!). In addition, any <xs:any> elements, // while not explicitly inherited, do not disappear. switch b := t.Base.(type) { case *xsd.ComplexType: t.Attributes = mergeAttributes(t, b) hasWildcard := false for _, el := range t.Elements { if el.Wildcard { hasWildcard = true break } } if hasWildcard { break } for _, el := range b.Elements { if el.Wildcard { t.Elements = append(t.Elements, el) break } } } } attributes, elements := cfg.filterFields(t) cfg.debugf("complexType %s: generating struct fields for %d elements and %d attributes", xsd.XMLName(t).Local, len(elements), len(attributes)) hasDefault := false for _, attr := range attributes { hasDefault = hasDefault || (attr.Default != "") tag := fmt.Sprintf(`xml:"%s,attr"`, attr.Name.Local) base, err := cfg.expr(attr.Type) if err != nil { return nil, fmt.Errorf("%s attribute %s: %v", t.Name.Local, attr.Name.Local, err) } fields = append(fields, ast.NewIdent(cfg.public(attr.Name)), base, gen.String(tag)) } for _, el := range elements { hasDefault = hasDefault || (el.Default != "") tag := fmt.Sprintf(`xml:"%s %s"`, el.Name.Space, el.Name.Local) base, err := cfg.expr(el.Type) if err != nil { return nil, fmt.Errorf("%s element %s: %v", t.Name.Local, el.Name.Local, err) } name := ast.NewIdent(cfg.public(el.Name)) if el.Wildcard { tag = `xml:",any"` if el.Plural { name = ast.NewIdent("Items") } else { name = ast.NewIdent("Item") } if b, ok := el.Type.(xsd.Builtin); ok && b == xsd.AnyType { cfg.debugf("complexType %s: defaulting wildcard element to []string", t.Name.Local) base = builtinExpr(xsd.String) } } if el.Plural { base = &ast.ArrayType{Elt: base} } fields = append(fields, name, base, gen.String(tag)) } expr := gen.Struct(fields...) s := spec{ name: cfg.typeName(t.Name), expr: expr, xsdType: t, } if hasDefault { unmarshal, marshal, err := cfg.genMarshalComplexType(t) if err != nil { //NOTE(droyo) may want to log this instead of stopping the generator return result, err } else { if unmarshal != nil { s.methods = append(s.methods, unmarshal) } if marshal != nil { s.methods = append(s.methods, marshal) } } } result = append(result, s) return result, nil }