Exemple #1
0
func parsePlural(el *xmltree.Element) bool {
	if min := parseInt(el.Attr("", "minOccurs")); min > 1 {
		return true
	} else if max := parseInt(el.Attr("", "maxOccurs")); max < 0 || max > 1 {
		return true
	}
	return false
}
Exemple #2
0
func parseAnyElement(ns string, el *xmltree.Element) Element {
	var base Type = AnyType
	typeattr := el.Attr("", "type")
	if typeattr != "" {
		base = parseType(el.Resolve(typeattr))
	}
	return Element{
		Plural:   parsePlural(el),
		Type:     base,
		Wildcard: true,
	}
}
Exemple #3
0
// http://www.w3.org/TR/2004/REC-xmlschema-1-20041028/structures.html#element-complexType
func (s *Schema) parseComplexType(root *xmltree.Element) *ComplexType {
	var t ComplexType
	var doc annotation
	t.Name = root.ResolveDefault(root.Attr("", "name"), s.TargetNS)
	t.Abstract = parseBool(root.Attr("", "abstract"))
	// We set this special attribute in a pre-processing step.
	t.Anonymous = (root.Attr("", "_isAnonymous") == "true")

	walk(root, func(el *xmltree.Element) {
		switch el.Name.Local {
		case "annotation":
			doc = doc.append(parseAnnotation(el))
		case "simpleContent":
			t.parseSimpleContent(s.TargetNS, el)
		case "complexContent":
			t.parseComplexContent(s.TargetNS, el)
		default:
			// a complex type defined without any simpleContent or
			// complexContent is interpreted as shorthand for complex
			// content that restricts anyType.
			children := root.Children
			root.Children = nil

			restrict := *root
			restrict.StartElement = xml.StartElement{
				Name: xml.Name{schemaNS, "restriction"},
			}
			restrict.SetAttr("", "base", restrict.Prefix(AnyType.Name()))
			restrict.Children = children

			content := *root
			content.StartElement = xml.StartElement{
				Name: xml.Name{schemaNS, "complexContent"},
			}
			content.Children = []xmltree.Element{restrict}
			root.Children = []xmltree.Element{content}

			t.parseComplexContent(s.TargetNS, &content)
		}
	})
	t.Doc += string(doc)
	return &t
}
Exemple #4
0
func lookupTargetNS(data ...[]byte) []string {
	var result []string
	for _, doc := range data {
		tree, err := xmltree.Parse(doc)
		if err != nil {
			continue
		}
		outer := xmltree.Element{
			Children: []xmltree.Element{*tree},
		}
		elts := outer.Search("http://www.w3.org/2001/XMLSchema", "schema")
		for _, el := range elts {
			ns := el.Attr("", "targetNamespace")
			if ns != "" {
				result = append(result, ns)
			}
		}
	}
	return result
}
Exemple #5
0
func (s *Schema) parseSimpleType(root *xmltree.Element) *SimpleType {
	var t SimpleType
	var doc annotation

	t.Name = root.ResolveDefault(root.Attr("", "name"), s.TargetNS)
	t.Anonymous = (root.Attr("", "_isAnonymous") == "true")
	walk(root, func(el *xmltree.Element) {
		switch el.Name.Local {
		case "restriction":
			t.Base = parseType(el.Resolve(el.Attr("", "base")))
			t.Restriction = parseSimpleRestriction(el)
		case "list":
			t.Base = parseType(el.Resolve(el.Attr("", "itemType")))
			t.List = true
		case "union":
			for _, name := range strings.Fields(el.Attr("", "memberTypes")) {
				type_ := parseType(el.Resolve(name))
				t.Union = append(t.Union, type_)
			}
		case "annotation":
			doc = doc.append(parseAnnotation(el))
		}
	})
	t.Doc = string(doc)
	return &t
}
Exemple #6
0
func parseAnnotation(el *xmltree.Element) (doc annotation) {
	if err := el.Unmarshal(&doc); err != nil {
		stop(err.Error())
	}
	return doc
}
Exemple #7
0
func parseAttribute(ns string, el *xmltree.Element) Attribute {
	var a Attribute
	var doc annotation
	// Non-QName xml attributes explicitly do *not* have a namespace.
	if name := el.Attr("", "name"); strings.Contains(name, ":") {
		a.Name = el.Resolve(el.Attr("", "name"))
	} else {
		a.Name.Local = name
	}
	a.Type = parseType(el.Resolve(el.Attr("", "type")))
	a.Default = el.Attr("", "default")
	a.Scope = el.Scope

	walk(el, func(el *xmltree.Element) {
		if el.Name.Local == "annotation" {
			doc = doc.append(parseAnnotation(el))
		}
	})
	a.Doc = string(doc)
	// Other attributes could be useful later. One such attribute is
	// wsdl:arrayType.
	a.Attr = el.StartElement.Attr
	return a
}
Exemple #8
0
func parseElement(ns string, el *xmltree.Element) Element {
	var doc annotation
	e := Element{
		Name:     el.ResolveDefault(el.Attr("", "name"), ns),
		Type:     parseType(el.Resolve(el.Attr("", "type"))),
		Default:  el.Attr("", "default"),
		Abstract: parseBool(el.Attr("", "abstract")),
		Nillable: parseBool(el.Attr("", "nillable")),
		Optional: (el.Attr("", "use") == "optional"),
		Plural:   parsePlural(el),
		Scope:    el.Scope,
	}

	walk(el, func(el *xmltree.Element) {
		if el.Name.Local == "annotation" {
			doc = doc.append(parseAnnotation(el))
		}
	})
	e.Doc = string(doc)
	e.Attr = el.StartElement.Attr
	return e
}
Exemple #9
0
func (s *Schema) parse(root *xmltree.Element, extra map[string]*xmltree.Element) (err error) {
	defer catchParseError(&err)

	// First pass: name all anonymous types with placeholder names.
	var (
		typeCounter int
		updateAttr  string
		accum       bool
	)
	for _, el := range root.SearchFunc(hasAnonymousType) {
		if el.Name.Space != schemaNS {
			continue
		}
		switch el.Name.Local {
		case "element", "attribute":
			updateAttr = "type"
			accum = false
		case "list":
			updateAttr = "itemType"
			accum = false
		case "restriction":
			updateAttr = "base"
			accum = false
		case "union":
			updateAttr = "memberTypes"
			accum = true
		default:
			return fmt.Errorf("Did not expect <%s> to have an anonymous type",
				el.Prefix(el.Name))
		}
		for _, t := range el.SearchFunc(isType) {
			typeCounter++
			name := anonTypeName(typeCounter, s.TargetNS)
			qname := el.Prefix(name)

			t.SetAttr("", "name", name.Local)
			t.SetAttr("", "_isAnonymous", "true")
			if accum {
				qname = el.Attr("", updateAttr) + " " + qname
			}
			el.SetAttr("", updateAttr, qname)
			if !accum {
				break
			}
		}
	}

	// Second pass: de-reference all group/element/attribute references.
	for _, el := range root.SearchFunc(hasAttr("", "ref")) {
		var found bool
		sameType := and(isElem(el.Name.Space, el.Name.Local), hasAttr("", "name"))
		if el.Name.Space != schemaNS {
			continue
		}
		ref := el.ResolveDefault(el.Attr("", "ref"), s.TargetNS)
		for ns, doc := range extra {
			for _, real := range doc.SearchFunc(sameType) {
				name := real.ResolveDefault(real.Attr("", "name"), ns)
				if name == ref {
					extraAttr := el.StartElement.Attr
					el.Content = real.Content
					el.StartElement = real.StartElement
					el.Children = real.Children
					el.Scope = *real.JoinScope(&el.Scope)
					// In XML Schema, it is valid to
					// reference another element and
					// at the same time add attributes
					// to it.	We handle this by merging
					// the attributes of elements and
					// their references.
					for _, attr := range extraAttr {
						if attr.Name.Local == "ref" {
							continue
						}
						el.SetAttr(attr.Name.Space, attr.Name.Local, attr.Value)
					}
					found = true
					break
				}
			}
		}
		if !found {
			return fmt.Errorf("could not dereference %s %s %s", el.Name.Local,
				el.Resolve(el.Attr("", "ref")).Space, el.Resolve(el.Attr("", "ref")).Local)
		}
	}

	// Final pass: parse all type declarations.
	for _, el := range root.Search(schemaNS, "complexType") {
		t := s.parseComplexType(el)
		s.Types[t.Name] = t
	}
	for _, el := range root.Search(schemaNS, "simpleType") {
		t := s.parseSimpleType(el)
		s.Types[t.Name] = t
	}

	return err
}