// SOAP arrays are declared as follows (unimportant fields ellided): // // <xs:complexType name="Array"> // <xs:attribute name="arrayType" type="xs:string" /> // <xs:any namespace="##any" minOccurs="0" maxOccurs="unbounded" /> // </xs:complexType> // // Then schemas that want to declare a fixed-type soap array do so like this: // // <xs:complexType name="IntArray"> // <xs:complexContent> // <xs:restriction base="soapenc:Array> // <xs:attribute ref="soapenc:arrayType" wsdl:arrayType="xs:int[]" /> // </xs:restriction> // </xs:complexContent> // </xs:complexType> // // XML Schema is wonderful, aint it? func (cfg *Config) parseSOAPArrayType(s xsd.Schema, t xsd.Type) xsd.Type { const soapenc = "http://schemas.xmlsoap.org/soap/encoding/" const wsdl = "http://schemas.xmlsoap.org/wsdl/" var itemType xml.Name c, ok := t.(*xsd.ComplexType) if !ok { return t } var attr []xsd.Attribute for _, v := range c.Attributes { if v.Name.Local != "arrayType" { attr = append(attr, v) continue } for _, a := range v.Attr { if (a.Name != xml.Name{wsdl, "arrayType"}) { continue } itemType = v.Resolve(a.Value) break } break } if itemType.Local == "" { return c } itemType.Local = strings.TrimSpace(itemType.Local) itemType.Local = strings.TrimSuffix(itemType.Local, "[]") if b := s.FindType(itemType); b != nil { c = cfg.overrideWildcardType(c, b) } else { cfg.logf("could not lookup item type %q in namespace %q", itemType.Local, itemType.Space) } // Have to remove arrayType from the "base" type, without affecting // others inheriting from this type. basep, ok := c.Base.(*xsd.ComplexType) if !ok { cfg.logf("type %s derives from non-complexType %s", c.Name.Local, xsd.XMLName(c.Base).Local) return c } base := *basep base.Attributes = make([]xsd.Attribute, 0, len(basep.Attributes)-1) for _, v := range basep.Attributes { if v.Name.Local != "arrayType" { base.Attributes = append(base.Attributes, v) } } c.Base = &base c.Attributes = attr return c }
func (cfg *Config) genAST(schema xsd.Schema, extra ...xsd.Schema) (*ast.File, error) { var errList errorList decls := make(map[string]spec) cfg.addStandardHelpers() collect := make(map[xml.Name]xsd.Type) for k, v := range schema.Types { collect[k] = v } for _, schema := range extra { for k, v := range schema.Types { collect[k] = v } } prev := schema.Types schema.Types = collect if cfg.preprocessType != nil { cfg.debugf("running user-defined pre-processing functions") for name, t := range prev { if t := cfg.preprocessType(schema, t); t != nil { prev[name] = t } } } schema.Types = prev cfg.debugf("generating Go source for schema %q", schema.TargetNS) typeList := cfg.flatten(schema.Types) for _, t := range typeList { specs, err := cfg.genTypeSpec(t) if err != nil { errList = append(errList, fmt.Errorf("generate type %q: %v", xsd.XMLName(t).Local, err)) } else { for _, s := range specs { decls[s.name] = s } } } if cfg.postprocessType != nil { cfg.debugf("running user-defined post-processing functions") for name, s := range decls { decls[name] = cfg.postprocessType(s) } } if len(errList) > 0 { return nil, errList } var result []ast.Decl keys := make([]string, 0, len(decls)) for name := range decls { keys = append(keys, name) } sort.Strings(keys) for _, name := range keys { info := decls[name] typeDecl := &ast.GenDecl{ Tok: token.TYPE, Specs: []ast.Spec{ &ast.TypeSpec{ Name: ast.NewIdent(name), Type: info.expr, }, }, } result = append(result, typeDecl) for _, f := range info.methods { result = append(result, f) } } if cfg.pkgname == "" { cfg.pkgname = "ws" } file := &ast.File{ Decls: result, Name: ast.NewIdent(cfg.pkgname), Doc: nil, } return file, nil }