Skip to content

Commit

Permalink
Rework loading of xsd schema and its imports
Browse files Browse the repository at this point in the history
It seems there are some circular dependencies in OVAL XSDs and hence we need
extra layer that avoids re-opening already loaded schemas
  • Loading branch information
isimluk committed May 26, 2020
1 parent 56fdf1b commit bc972e7
Show file tree
Hide file tree
Showing 3 changed files with 54 additions and 19 deletions.
22 changes: 4 additions & 18 deletions pkg/xsd/schema.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ package xsd
import (
"encoding/xml"
"fmt"
"os"
"io"
"path/filepath"
)

Expand All @@ -20,28 +20,14 @@ type Schema struct {
ModulesPath string `xml:"-"`
}

func Parse(xsdPath string) (*Schema, error) {
f, err := os.Open(xsdPath)
if err != nil {
return nil, err
}
defer f.Close()

func parseSchema(f io.Reader) (*Schema, error) {
schema := Schema{importedModules: map[string]*Schema{}}
d := xml.NewDecoder(f)

if err := d.Decode(&schema); err != nil {
return nil, fmt.Errorf("Error decoding XSD: %s", err)
}

dir := filepath.Dir(xsdPath)
for idx, _ := range schema.Imports {
if err := schema.Imports[idx].Load(dir); err != nil {
return nil, err
}
}
schema.compile()

return &schema, nil
}

Expand Down Expand Up @@ -157,7 +143,7 @@ type Import struct {
ImportedSchema *Schema `xml:"-"`
}

func (i *Import) Load(baseDir string) (err error) {
i.ImportedSchema, err = Parse(filepath.Join(baseDir, i.SchemaLocation))
func (i *Import) load(ws *Workspace, baseDir string) (err error) {
i.ImportedSchema, err = ws.loadXsd(filepath.Join(baseDir, i.SchemaLocation))
return
}
48 changes: 48 additions & 0 deletions pkg/xsd/workspace.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
package xsd

import (
"fmt"
"os"
"path/filepath"
)

type Workspace struct {
PrimarySchema *Schema
Cache map[string]*Schema
}

func NewWorkspace(xsdPath string) (*Workspace, error) {
ws := Workspace{Cache: map[string]*Schema{}}
var err error
ws.PrimarySchema, err = ws.loadXsd(xsdPath)
return &ws, err
}

func (ws *Workspace) loadXsd(xsdPath string) (*Schema, error) {
cached, found := ws.Cache[xsdPath]
if found {
return cached, nil
}
fmt.Println("\tParsing:", xsdPath)

f, err := os.Open(xsdPath)
if err != nil {
return nil, err
}
defer f.Close()

schema, err := parseSchema(f)
if err != nil {
return nil, err
}
ws.Cache[xsdPath] = schema

dir := filepath.Dir(xsdPath)
for idx, _ := range schema.Imports {
if err := schema.Imports[idx].load(ws, dir); err != nil {
return nil, err
}
}
schema.compile()
return schema, nil
}
3 changes: 2 additions & 1 deletion pkg/xsd2go/generate.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,11 @@ import (

func Convert(xsdPath, goModule, outputDir string) error {
fmt.Printf("Processing '%s'\n", xsdPath)
schema, err := xsd.Parse(xsdPath)
ws, err := xsd.NewWorkspace(xsdPath)
if err != nil {
return err
}
schema := ws.PrimarySchema
schema.ModulesPath = fmt.Sprintf("%s/%s", goModule, outputDir)

for _, imp := range schema.Imports {
Expand Down

0 comments on commit bc972e7

Please # to comment.