func Details()

in lib/xml/xml.go [61:138]


func Details(doc []byte) (map[string]Detail, error) {
	schema, err := xsd.Parse(doc)
	if err != nil {
		return nil, err
	}

	tree := make(map[string]string)
	leaves := make(map[string]Detail)
	for _, s := range schema {
		for n, t := range s.Types {
			switch t := t.(type) {
			case xsd.Builtin:
			case *xsd.SimpleType:
			case *xsd.ComplexType:
				// Ignore external name-spaced names.
				if t.Name.Space != "" {
					continue
				}
				// Ignore anonymous node and the root.
				if strings.HasPrefix(n.Local, "_") {
					continue
				}
				for _, e := range t.Elements {
					var d Detail
					tree[e.Name.Local] = n.Local
					switch builtinTypeFor(e.Type) {
					case xsd.Boolean:
						d.Type = BoolType
					case xsd.Int, xsd.Integer, xsd.Long, xsd.NonNegativeInteger,
						xsd.NonPositiveInteger, xsd.PositiveInteger, xsd.Short,
						xsd.UnsignedByte, xsd.UnsignedInt, xsd.UnsignedLong, xsd.UnsignedShort:
						d.Type = IntType
					case xsd.Decimal, xsd.Double, xsd.Float:
						d.Type = FloatType
					}
					d.Plural = e.Plural
					if d.isZero() {
						continue
					}
					leaves[e.Name.Local] = d
				}
			default:
				panic(fmt.Sprintf("unknown type: %T", t))
			}
		}
	}

	details := Detail{Children: make(map[string]Detail)}
	var path []string
	for p, d := range leaves {
		path = append(path[:0], p)
		for i := 0; i <= len(tree); i++ {
			parent, ok := tree[p]
			if !ok {
				break
			}
			path = append(path, parent)
			p = parent
		}
		reverse(path)

		n := details
		for i, e := range path {
			c := n.Children[e]
			if c.Children == nil && i < len(path)-1 {
				c.Children = make(map[string]Detail)
			}
			if i == len(path)-1 {
				c.Type = d.Type
				c.Plural = d.Plural
			}
			n.Children[e] = c
			n = c
		}
	}

	return details.Children, nil
}