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 }
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 }