예제 #1
0
파일: xsdgen.go 프로젝트: DrGo/go-xml
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
}
예제 #2
0
파일: parse.go 프로젝트: DrGo/go-xml
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
}