From 7d14b6362fb14a82c62f05a3f7493be63fa0adc1 Mon Sep 17 00:00:00 2001 From: David Alpert Date: Thu, 11 Mar 2021 12:45:24 -0600 Subject: [PATCH 1/2] teach xsd.Schema how to merge type maps a new MergeTypes method is added to the xsd.Schema type which merges the types from one xsd.Schema into another provided that the TargetNS values are equivalent. this MergeTypes method is then used when collecting the map of namespaces to schemas so that when a single schema is spread across multiple files (e.g. when imports are used to tie them together) the types from a namespace are all collected together, regardless of which files they came from. this allows the resolvePartialTypes method to operate as expected, since following the imports will now merge the types into a single xsd.Schema. --- xsd/xsd.go | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/xsd/xsd.go b/xsd/xsd.go index 1c1f6bb..35a58f3 100644 --- a/xsd/xsd.go +++ b/xsd/xsd.go @@ -19,6 +19,7 @@ import ( "fmt" "io" "regexp" + "strings" "time" "aqwari.net/xml/xmltree" @@ -110,6 +111,19 @@ type Schema struct { Doc string } +// MergeTypes adds the types from the incoming schema into +// the receiving schema, returns error if the schemas have +// different target namespaces. +func (s *Schema) MergeTypes(incoming *Schema) error { + if !strings.EqualFold(s.TargetNS, incoming.TargetNS) { + return fmt.Errorf("cannot merge types from %s into %s", incoming.TargetNS, s.TargetNS) + } + for n,t := range incoming.Types { + s.Types[n] = t + } + return nil +} + // FindType looks for a type by its canonical name. In addition to the types // declared in a Schema, FindType will also search through the types that // a Schema's top-level types are derived from. FindType will return nil if From 6d8d9b0415eae35df4a6cc14bda333c32f4891cd Mon Sep 17 00:00:00 2001 From: David Alpert Date: Thu, 11 Mar 2021 12:47:45 -0600 Subject: [PATCH 2/2] resolve targetNS collisions by merge rather than replace previously when a single target namespace was spread across multiple files, the last schema file read for each target namespace would clobber any previously read type maps this commit adds some minimal target namespace collision detection and delegates to the xsd.Schema class the responsibility to resolve that conflict. --- xsd/parse.go | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/xsd/parse.go b/xsd/parse.go index 0e6890d..6db1066 100644 --- a/xsd/parse.go +++ b/xsd/parse.go @@ -147,7 +147,14 @@ func Parse(docs ...[]byte) ([]Schema, error) { if err := s.parse(root); err != nil { return nil, err } - parsed[tns] = s + if existingSchema, found := parsed[tns]; found { + err = existingSchema.MergeTypes(&s) + if err != nil { + return nil, fmt.Errorf("error merging types into existing schema: %v", err) + } + } else { + parsed[tns] = s + } } for _, s := range parsed {