Beispiel #1
0
// 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
}
Beispiel #2
0
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
}