From 85d3f9bcbc784f267647eb1cf1e5df73791471ef Mon Sep 17 00:00:00 2001 From: henryolik <9393124+henryolik@users.noreply.github.com> Date: Wed, 29 Nov 2023 17:49:59 +0100 Subject: [PATCH 1/9] wsdlgen: added -f option to follow imports --- wsdl/wsdl.go | 1 + wsdlgen/cli.go | 23 ++++++++++++++--------- wsdlgen/wsdlgen.go | 22 ++++++++++++++-------- xsdgen/cli.go | 12 ++++++------ xsdgen/config.go | 2 +- 5 files changed, 36 insertions(+), 24 deletions(-) diff --git a/wsdl/wsdl.go b/wsdl/wsdl.go index 9abe371b..30b0bb09 100644 --- a/wsdl/wsdl.go +++ b/wsdl/wsdl.go @@ -29,6 +29,7 @@ type Definition struct { Ports []Port Message map[xml.Name]Message TargetNS string + Types *xmltree.Element } func (def *Definition) String() string { diff --git a/wsdlgen/cli.go b/wsdlgen/cli.go index 93bf2a5d..fe6d3d35 100644 --- a/wsdlgen/cli.go +++ b/wsdlgen/cli.go @@ -26,15 +26,16 @@ func (cfg *Config) GenSource(files ...string) ([]byte, error) { // command-line interfaces to the wsdlgen package. func (cfg *Config) GenCLI(arguments ...string) error { var ( - err error - replaceRules commandline.ReplaceRuleList - ports commandline.Strings - fs = flag.NewFlagSet("wsdlgen", flag.ExitOnError) - packageName = fs.String("pkg", "", "name of the generated package") - comment = fs.String("c", "", "First line of package-level comments") - output = fs.String("o", "wsdlgen_output.go", "name of the output file") - verbose = fs.Bool("v", false, "print verbose output") - debug = fs.Bool("vv", false, "print debug output") + err error + replaceRules commandline.ReplaceRuleList + ports commandline.Strings + fs = flag.NewFlagSet("wsdlgen", flag.ExitOnError) + packageName = fs.String("pkg", "", "name of the generated package") + comment = fs.String("c", "", "First line of package-level comments") + followImports = fs.Bool("f", false, "follow xsd import statements; load imported references recursively into scope") + output = fs.String("o", "wsdlgen_output.go", "name of the output file") + verbose = fs.Bool("v", false, "print verbose output") + debug = fs.Bool("vv", false, "print debug output") ) fs.Var(&replaceRules, "r", "replacement rule 'regex -> repl' (can be used multiple times)") fs.Var(&ports, "port", "gen code for this port (can be used multiple times)") @@ -60,6 +61,10 @@ func (cfg *Config) GenCLI(arguments ...string) error { if len(ports) > 0 { cfg.Option(OnlyPorts(ports...)) } + + cfg.XSDOption(xsdgen.FollowImports(*followImports)) + cfg.xsdgen.FilesRead = make(map[string]bool) + for _, r := range replaceRules { cfg.XSDOption(xsdgen.Replace(r.From.String(), r.To)) } diff --git a/wsdlgen/wsdlgen.go b/wsdlgen/wsdlgen.go index 06e47bb6..107faa08 100644 --- a/wsdlgen/wsdlgen.go +++ b/wsdlgen/wsdlgen.go @@ -20,7 +20,6 @@ import ( "go/ast" "golang.org/x/text/cases" "golang.org/x/text/language" - "os" ) var caser = cases.Title(language.English, cases.NoLower) @@ -100,15 +99,22 @@ func (cfg *Config) GenAST(files ...string) (*ast.File, error) { cfg.pkgHeader = fmt.Sprintf("Package %s", cfg.pkgName) } docs := make([][]byte, 0, len(files)) - for _, filename := range files { - if data, err := os.ReadFile(filename); err != nil { - return nil, err - } else { - cfg.debugf("read %s", filename) - docs = append(docs, data) - } + //for _, filename := range files { + // if data, err := os.ReadFile(filename); err != nil { + // return nil, err + // } else { + // cfg.debugf("read %s", filename) + // docs = append(docs, data) + // } + //} + + data, err := cfg.xsdgen.ReadFiles(files...) + if err != nil { + return nil, err } + docs = append(docs, data...) + cfg.debugf("parsing WSDL file %s", files[0]) def, err := wsdl.Parse(docs[0]) if err != nil { diff --git a/xsdgen/cli.go b/xsdgen/cli.go index c437ffef..adf620a3 100644 --- a/xsdgen/cli.go +++ b/xsdgen/cli.go @@ -55,8 +55,8 @@ func (cfg *Config) GenCode(data ...[]byte) (*Code, error) { // GenAST creates an *ast.File containing type declarations and // associated methods based on a set of XML schema. func (cfg *Config) GenAST(files ...string) (*ast.File, error) { - cfg.filesRead = make(map[string]bool) - data, err := cfg.readFiles(files...) + cfg.FilesRead = make(map[string]bool) + data, err := cfg.ReadFiles(files...) code, err := cfg.GenCode(data...) if err != nil { return nil, err @@ -64,10 +64,10 @@ func (cfg *Config) GenAST(files ...string) (*ast.File, error) { return code.GenAST() } -func (cfg *Config) readFiles(files ...string) ([][]byte, error) { +func (cfg *Config) ReadFiles(files ...string) ([][]byte, error) { data := make([][]byte, 0, len(files)) for _, filename := range files { - if _, ok := cfg.filesRead[filename]; ok { + if _, ok := cfg.FilesRead[filename]; ok { // skip reading the file again continue } @@ -80,7 +80,7 @@ func (cfg *Config) readFiles(files ...string) ([][]byte, error) { return nil, err } cfg.debugf("read %s(%s)", path, filename) - cfg.filesRead[filename] = true + cfg.FilesRead[filename] = true if cfg.followImports { dir := filepath.Dir(path) importedRefs, err := xsd.Imports(b) @@ -95,7 +95,7 @@ func (cfg *Config) readFiles(files ...string) ([][]byte, error) { importedFiles = append(importedFiles, filepath.Join(dir, r.Location)) } } - referencedData, err := cfg.readFiles(importedFiles...) + referencedData, err := cfg.ReadFiles(importedFiles...) if err != nil { return nil, fmt.Errorf("error reading imported files: %v", err) } diff --git a/xsdgen/config.go b/xsdgen/config.go index 15b7ee7d..93a1063f 100644 --- a/xsdgen/config.go +++ b/xsdgen/config.go @@ -50,7 +50,7 @@ type Config struct { allowTypes map[xml.Name]bool // keep track of files that are read already to avoid reading it again - filesRead map[string]bool + FilesRead map[string]bool } type typeTransform func(xsd.Schema, xsd.Type) xsd.Type From 37a335aeec85f7641173bb73a1626b7306c87df9 Mon Sep 17 00:00:00 2001 From: henryolik <9393124+henryolik@users.noreply.github.com> Date: Thu, 30 Nov 2023 14:42:47 +0100 Subject: [PATCH 2/9] Fix readfile error messages --- xsdgen/cli.go | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/xsdgen/cli.go b/xsdgen/cli.go index adf620a3..cfc21ac4 100644 --- a/xsdgen/cli.go +++ b/xsdgen/cli.go @@ -15,7 +15,7 @@ import ( ) // GenCode reads all xml schema definitions from the provided -// data. If succesful, the returned *Code value can be used to +// data. If successful, the returned *Code value can be used to // lookup identifiers and generate Go code. func (cfg *Config) GenCode(data ...[]byte) (*Code, error) { if len(cfg.namespaces) == 0 { @@ -57,10 +57,15 @@ func (cfg *Config) GenCode(data ...[]byte) (*Code, error) { func (cfg *Config) GenAST(files ...string) (*ast.File, error) { cfg.FilesRead = make(map[string]bool) data, err := cfg.ReadFiles(files...) + if err != nil { + return nil, err + } + code, err := cfg.GenCode(data...) if err != nil { return nil, err } + return code.GenAST() } From 4dc839f2e65ff48a35ac7c0029d7f8eea2064b3e Mon Sep 17 00:00:00 2001 From: henryolik <9393124+henryolik@users.noreply.github.com> Date: Wed, 6 Dec 2023 15:13:57 +0100 Subject: [PATCH 3/9] Staticcheck fixes, ignore imports without a path, updated tests --- gentests/_testgen/testgen.go | 2 +- gentests/bindata/bindata_test.go | 4 +- gentests/books/books_test.go | 4 +- wsdlgen/cli.go | 2 +- wsdlgen/examples/chemspell/wsdlgen_output.go | 5 +- wsdlgen/examples/forecast/wsdlgen_output.go | 110 +++++++++---------- wsdlgen/wsdlgen.go | 10 +- wsdlgen/wsdlgen_test.go | 2 +- xmltree/example_test.go | 2 +- xmltree/xmltree.go | 10 +- xmltree/xmltree_test.go | 23 ++-- xsd/parse.go | 3 +- xsd/xsd.go | 2 +- xsdgen/cli.go | 15 ++- xsdgen/config.go | 20 ++-- xsdgen/example_test.go | 4 +- xsdgen/xsdgen_test.go | 24 ++-- 17 files changed, 123 insertions(+), 119 deletions(-) diff --git a/gentests/_testgen/testgen.go b/gentests/_testgen/testgen.go index 50b901e9..bbe25d09 100644 --- a/gentests/_testgen/testgen.go +++ b/gentests/_testgen/testgen.go @@ -143,7 +143,7 @@ func genXSDTests(cfg xsdgen.Config, data []byte, pkg string) (code, tests *ast.F t.Fatal("expected one sample file, found ", samples) } - input, err := ioutil.ReadFile(samples[0]) + input, err := os.ReadFile(samples[0]) if err != nil { t.Fatal(err) } diff --git a/gentests/bindata/bindata_test.go b/gentests/bindata/bindata_test.go index 44422a85..8dea39be 100644 --- a/gentests/bindata/bindata_test.go +++ b/gentests/bindata/bindata_test.go @@ -4,7 +4,7 @@ package bindata import ( "encoding/xml" - "io/ioutil" + "os" "path/filepath" "testing" @@ -23,7 +23,7 @@ func TestBindata(t *testing.T) { if len(samples) != 1 { t.Fatal("expected one sample file, found ", samples) } - input, err := ioutil.ReadFile(samples[0]) + input, err := os.ReadFile(samples[0]) if err != nil { t.Fatal(err) } diff --git a/gentests/books/books_test.go b/gentests/books/books_test.go index ef4b0cd9..0739eadf 100644 --- a/gentests/books/books_test.go +++ b/gentests/books/books_test.go @@ -4,7 +4,7 @@ package books import ( "encoding/xml" - "io/ioutil" + "os" "path/filepath" "testing" @@ -23,7 +23,7 @@ func TestBooks(t *testing.T) { if len(samples) != 1 { t.Fatal("expected one sample file, found ", samples) } - input, err := ioutil.ReadFile(samples[0]) + input, err := os.ReadFile(samples[0]) if err != nil { t.Fatal(err) } diff --git a/wsdlgen/cli.go b/wsdlgen/cli.go index fe6d3d35..e24300ab 100644 --- a/wsdlgen/cli.go +++ b/wsdlgen/cli.go @@ -43,7 +43,7 @@ func (cfg *Config) GenCLI(arguments ...string) error { return err } if fs.NArg() == 0 { - return errors.New("Usage: wsdlgen [-r rule] [-o file] [-port name] [-pkg pkg] file ...") + return errors.New("usage: wsdlgen [-r rule] [-o file] [-port name] [-pkg pkg] file ... ") } if *debug { diff --git a/wsdlgen/examples/chemspell/wsdlgen_output.go b/wsdlgen/examples/chemspell/wsdlgen_output.go index 000eaadb..6ba89991 100644 --- a/wsdlgen/examples/chemspell/wsdlgen_output.go +++ b/wsdlgen/examples/chemspell/wsdlgen_output.go @@ -1,7 +1,6 @@ // Code generated by wsdlgen. DO NOT EDIT. // Package chemspell accesses the NLM ChemSpell web service. -// package chemspell import ( @@ -18,10 +17,10 @@ type ArrayOfxsdstring []string func (a ArrayOfxsdstring) MarshalXML(e *xml.Encoder, start xml.StartElement) error { var output struct { ArrayType string `xml:"http://schemas.xmlsoap.org/wsdl/ arrayType,attr"` - Items []string `xml:" item"` + Items []string `xml:"item"` } output.Items = []string(a) - start.Attr = append(start.Attr, xml.Attr{Name: xml.Name{"", "xmlns:ns1"}, Value: "http://www.w3.org/2001/XMLSchema"}) + start.Attr = append(start.Attr, xml.Attr{Name: xml.Name{Space: "", Local: "xmlns:ns1"}, Value: "http://www.w3.org/2001/XMLSchema"}) output.ArrayType = "ns1:string[]" return e.EncodeElement(&output, start) } diff --git a/wsdlgen/examples/forecast/wsdlgen_output.go b/wsdlgen/examples/forecast/wsdlgen_output.go index 10523dde..9c5b546c 100644 --- a/wsdlgen/examples/forecast/wsdlgen_output.go +++ b/wsdlgen/examples/forecast/wsdlgen_output.go @@ -83,61 +83,61 @@ type Sector string type Unit string type WeatherParameters struct { - Maxt bool `xml:"http://graphical.weather.gov/xml/DWMLgen/schema/DWML.xsd maxt"` - Mint bool `xml:"http://graphical.weather.gov/xml/DWMLgen/schema/DWML.xsd mint"` - Temp bool `xml:"http://graphical.weather.gov/xml/DWMLgen/schema/DWML.xsd temp"` - Dew bool `xml:"http://graphical.weather.gov/xml/DWMLgen/schema/DWML.xsd dew"` - Pop12 bool `xml:"http://graphical.weather.gov/xml/DWMLgen/schema/DWML.xsd pop12"` - Qpf bool `xml:"http://graphical.weather.gov/xml/DWMLgen/schema/DWML.xsd qpf"` - Sky bool `xml:"http://graphical.weather.gov/xml/DWMLgen/schema/DWML.xsd sky"` - Snow bool `xml:"http://graphical.weather.gov/xml/DWMLgen/schema/DWML.xsd snow"` - Wspd bool `xml:"http://graphical.weather.gov/xml/DWMLgen/schema/DWML.xsd wspd"` - Wdir bool `xml:"http://graphical.weather.gov/xml/DWMLgen/schema/DWML.xsd wdir"` - Wx bool `xml:"http://graphical.weather.gov/xml/DWMLgen/schema/DWML.xsd wx"` - Waveh bool `xml:"http://graphical.weather.gov/xml/DWMLgen/schema/DWML.xsd waveh"` - Icons bool `xml:"http://graphical.weather.gov/xml/DWMLgen/schema/DWML.xsd icons"` - Rh bool `xml:"http://graphical.weather.gov/xml/DWMLgen/schema/DWML.xsd rh"` - Appt bool `xml:"http://graphical.weather.gov/xml/DWMLgen/schema/DWML.xsd appt"` - Incw34 bool `xml:"http://graphical.weather.gov/xml/DWMLgen/schema/DWML.xsd incw34"` - Incw50 bool `xml:"http://graphical.weather.gov/xml/DWMLgen/schema/DWML.xsd incw50"` - Incw64 bool `xml:"http://graphical.weather.gov/xml/DWMLgen/schema/DWML.xsd incw64"` - Cumw34 bool `xml:"http://graphical.weather.gov/xml/DWMLgen/schema/DWML.xsd cumw34"` - Cumw50 bool `xml:"http://graphical.weather.gov/xml/DWMLgen/schema/DWML.xsd cumw50"` - Cumw64 bool `xml:"http://graphical.weather.gov/xml/DWMLgen/schema/DWML.xsd cumw64"` - Critfireo bool `xml:"http://graphical.weather.gov/xml/DWMLgen/schema/DWML.xsd critfireo"` - Dryfireo bool `xml:"http://graphical.weather.gov/xml/DWMLgen/schema/DWML.xsd dryfireo"` - Conhazo bool `xml:"http://graphical.weather.gov/xml/DWMLgen/schema/DWML.xsd conhazo"` - Ptornado bool `xml:"http://graphical.weather.gov/xml/DWMLgen/schema/DWML.xsd ptornado"` - Phail bool `xml:"http://graphical.weather.gov/xml/DWMLgen/schema/DWML.xsd phail"` - Ptstmwinds bool `xml:"http://graphical.weather.gov/xml/DWMLgen/schema/DWML.xsd ptstmwinds"` - Pxtornado bool `xml:"http://graphical.weather.gov/xml/DWMLgen/schema/DWML.xsd pxtornado"` - Pxhail bool `xml:"http://graphical.weather.gov/xml/DWMLgen/schema/DWML.xsd pxhail"` - Pxtstmwinds bool `xml:"http://graphical.weather.gov/xml/DWMLgen/schema/DWML.xsd pxtstmwinds"` - Ptotsvrtstm bool `xml:"http://graphical.weather.gov/xml/DWMLgen/schema/DWML.xsd ptotsvrtstm"` - Pxtotsvrtstm bool `xml:"http://graphical.weather.gov/xml/DWMLgen/schema/DWML.xsd pxtotsvrtstm"` - Tmpabv14d bool `xml:"http://graphical.weather.gov/xml/DWMLgen/schema/DWML.xsd tmpabv14d"` - Tmpblw14d bool `xml:"http://graphical.weather.gov/xml/DWMLgen/schema/DWML.xsd tmpblw14d"` - Tmpabv30d bool `xml:"http://graphical.weather.gov/xml/DWMLgen/schema/DWML.xsd tmpabv30d"` - Tmpblw30d bool `xml:"http://graphical.weather.gov/xml/DWMLgen/schema/DWML.xsd tmpblw30d"` - Tmpabv90d bool `xml:"http://graphical.weather.gov/xml/DWMLgen/schema/DWML.xsd tmpabv90d"` - Tmpblw90d bool `xml:"http://graphical.weather.gov/xml/DWMLgen/schema/DWML.xsd tmpblw90d"` - Prcpabv14d bool `xml:"http://graphical.weather.gov/xml/DWMLgen/schema/DWML.xsd prcpabv14d"` - Prcpblw14d bool `xml:"http://graphical.weather.gov/xml/DWMLgen/schema/DWML.xsd prcpblw14d"` - Prcpabv30d bool `xml:"http://graphical.weather.gov/xml/DWMLgen/schema/DWML.xsd prcpabv30d"` - Prcpblw30d bool `xml:"http://graphical.weather.gov/xml/DWMLgen/schema/DWML.xsd prcpblw30d"` - Prcpabv90d bool `xml:"http://graphical.weather.gov/xml/DWMLgen/schema/DWML.xsd prcpabv90d"` - Prcpblw90d bool `xml:"http://graphical.weather.gov/xml/DWMLgen/schema/DWML.xsd prcpblw90d"` - Precipar bool `xml:"http://graphical.weather.gov/xml/DWMLgen/schema/DWML.xsd precipa_r"` - Skyr bool `xml:"http://graphical.weather.gov/xml/DWMLgen/schema/DWML.xsd sky_r"` - Tdr bool `xml:"http://graphical.weather.gov/xml/DWMLgen/schema/DWML.xsd td_r"` - Tempr bool `xml:"http://graphical.weather.gov/xml/DWMLgen/schema/DWML.xsd temp_r"` - Wdirr bool `xml:"http://graphical.weather.gov/xml/DWMLgen/schema/DWML.xsd wdir_r"` - Wspdr bool `xml:"http://graphical.weather.gov/xml/DWMLgen/schema/DWML.xsd wspd_r"` - Wwa bool `xml:"http://graphical.weather.gov/xml/DWMLgen/schema/DWML.xsd wwa"` - Wgust bool `xml:"http://graphical.weather.gov/xml/DWMLgen/schema/DWML.xsd wgust"` - Iceaccum bool `xml:"http://graphical.weather.gov/xml/DWMLgen/schema/DWML.xsd iceaccum"` - Maxrh bool `xml:"http://graphical.weather.gov/xml/DWMLgen/schema/DWML.xsd maxrh"` - Minrh bool `xml:"http://graphical.weather.gov/xml/DWMLgen/schema/DWML.xsd minrh"` + Maxt bool `xml:"maxt"` + Mint bool `xml:"mint"` + Temp bool `xml:"temp"` + Dew bool `xml:"dew"` + Pop12 bool `xml:"pop12"` + Qpf bool `xml:"qpf"` + Sky bool `xml:"sky"` + Snow bool `xml:"snow"` + Wspd bool `xml:"wspd"` + Wdir bool `xml:"wdir"` + Wx bool `xml:"wx"` + Waveh bool `xml:"waveh"` + Icons bool `xml:"icons"` + Rh bool `xml:"rh"` + Appt bool `xml:"appt"` + Incw34 bool `xml:"incw34"` + Incw50 bool `xml:"incw50"` + Incw64 bool `xml:"incw64"` + Cumw34 bool `xml:"cumw34"` + Cumw50 bool `xml:"cumw50"` + Cumw64 bool `xml:"cumw64"` + Critfireo bool `xml:"critfireo"` + Dryfireo bool `xml:"dryfireo"` + Conhazo bool `xml:"conhazo"` + Ptornado bool `xml:"ptornado"` + Phail bool `xml:"phail"` + Ptstmwinds bool `xml:"ptstmwinds"` + Pxtornado bool `xml:"pxtornado"` + Pxhail bool `xml:"pxhail"` + Pxtstmwinds bool `xml:"pxtstmwinds"` + Ptotsvrtstm bool `xml:"ptotsvrtstm"` + Pxtotsvrtstm bool `xml:"pxtotsvrtstm"` + Tmpabv14d bool `xml:"tmpabv14d"` + Tmpblw14d bool `xml:"tmpblw14d"` + Tmpabv30d bool `xml:"tmpabv30d"` + Tmpblw30d bool `xml:"tmpblw30d"` + Tmpabv90d bool `xml:"tmpabv90d"` + Tmpblw90d bool `xml:"tmpblw90d"` + Prcpabv14d bool `xml:"prcpabv14d"` + Prcpblw14d bool `xml:"prcpblw14d"` + Prcpabv30d bool `xml:"prcpabv30d"` + Prcpblw30d bool `xml:"prcpblw30d"` + Prcpabv90d bool `xml:"prcpabv90d"` + Prcpblw90d bool `xml:"prcpblw90d"` + Precipar bool `xml:"precipa_r"` + Skyr bool `xml:"sky_r"` + Tdr bool `xml:"td_r"` + Tempr bool `xml:"temp_r"` + Wdirr bool `xml:"wdir_r"` + Wspdr bool `xml:"wspd_r"` + Wwa bool `xml:"wwa"` + Wgust bool `xml:"wgust"` + Iceaccum bool `xml:"iceaccum"` + Maxrh bool `xml:"maxrh"` + Minrh bool `xml:"minrh"` } // Must match the pattern \d{5}(\-\d{4})? diff --git a/wsdlgen/wsdlgen.go b/wsdlgen/wsdlgen.go index 107faa08..2bdd0528 100644 --- a/wsdlgen/wsdlgen.go +++ b/wsdlgen/wsdlgen.go @@ -98,16 +98,8 @@ func (cfg *Config) GenAST(files ...string) (*ast.File, error) { if cfg.pkgHeader == "" { cfg.pkgHeader = fmt.Sprintf("Package %s", cfg.pkgName) } - docs := make([][]byte, 0, len(files)) - //for _, filename := range files { - // if data, err := os.ReadFile(filename); err != nil { - // return nil, err - // } else { - // cfg.debugf("read %s", filename) - // docs = append(docs, data) - // } - //} + docs := make([][]byte, 0, len(files)) data, err := cfg.xsdgen.ReadFiles(files...) if err != nil { return nil, err diff --git a/wsdlgen/wsdlgen_test.go b/wsdlgen/wsdlgen_test.go index 01ae00c0..657818ce 100644 --- a/wsdlgen/wsdlgen_test.go +++ b/wsdlgen/wsdlgen_test.go @@ -26,7 +26,7 @@ func testGen(t *testing.T, files ...string) { cfg.xsdgen.Option(xsdgen.DefaultOptions...) cfg.xsdgen.Option(xsdgen.UseFieldNames()) - args := []string{"-vv", "-o", outputFile.Name()} + args := []string{"-vv", "-f", "-o", outputFile.Name()} err = cfg.GenCLI(append(args, files...)...) if err != nil { t.Error(err) diff --git a/xmltree/example_test.go b/xmltree/example_test.go index 3f243aa0..77c47bd5 100644 --- a/xmltree/example_test.go +++ b/xmltree/example_test.go @@ -225,7 +225,7 @@ func ExampleMarshal() { // } -func ExampleMarshalNested() { +func ExampleMarshal_nested() { input := []byte(` diff --git a/xmltree/xmltree.go b/xmltree/xmltree.go index 10d15bde..902af173 100644 --- a/xmltree/xmltree.go +++ b/xmltree/xmltree.go @@ -131,7 +131,7 @@ func (scope *Scope) ResolveDefault(qname, defaultns string) xml.Name { if defaultns == "" || strings.Contains(qname, ":") { return scope.Resolve(qname) } - return xml.Name{defaultns, qname} + return xml.Name{Space: defaultns, Local: qname} } // Prefix is the inverse of Resolve. It uses the closest prefix @@ -166,9 +166,9 @@ func (scope *Scope) pushNS(tag xml.StartElement) []xml.Attr { var newAttrs []xml.Attr for _, attr := range tag.Attr { if attr.Name.Space == "xmlns" { - ns = append(ns, xml.Name{attr.Value, attr.Name.Local}) + ns = append(ns, xml.Name{Space: attr.Value, Local: attr.Name.Local}) } else if attr.Name.Local == "xmlns" { - ns = append(ns, xml.Name{attr.Value, ""}) + ns = append(ns, xml.Name{Space: attr.Value}) } else { newAttrs = append(newAttrs, attr) } @@ -269,7 +269,7 @@ walk: el.Children = append(el.Children, child) case xml.EndElement: if tok.Name != el.Name { - return fmt.Errorf("Expecting , got ", el.Prefix(el.Name), el.Prefix(tok.Name)) + return fmt.Errorf("expecting , got ", el.Prefix(el.Name), el.Prefix(tok.Name)) } el.Content = data[int(begin):int(end)] break walk @@ -308,7 +308,7 @@ func (el *Element) SetAttr(space, local, value string) { } } el.StartElement.Attr = append(el.StartElement.Attr, xml.Attr{ - Name: xml.Name{space, local}, + Name: xml.Name{Space: space, Local: local}, Value: value, }) } diff --git a/xmltree/xmltree_test.go b/xmltree/xmltree_test.go index 11990203..663d483f 100644 --- a/xmltree/xmltree_test.go +++ b/xmltree/xmltree_test.go @@ -196,7 +196,7 @@ func TestNSResolution(t *testing.T) { } defaultns := root.SearchFunc(func(el *Element) bool { - if (el.Name != xml.Name{"http://schemas.xmlsoap.org/wsdl/", "binding"}) { + if (el.Name != xml.Name{Space: "http://schemas.xmlsoap.org/wsdl/", Local: "binding"}) { return false } return el.Attr("", "name") == "wseDocReciboSoap12" @@ -273,16 +273,21 @@ func TestUnmarshal(t *testing.T) { } var v searchItem const changedURL = "http://i-changed-this/" - var item *Element - for _, item = range root.Search("", "item") { - for i, c := range item.Children { - if c.Name.Local == "URL" { - item.Children[i].Content = []byte(changedURL) - } + + items := root.Search("", "item") + if len(items) < 1 { + t.Errorf("no element with name \"item\" found") + } + + item := items[0] + + for i, c := range item.Children { + if c.Name.Local == "URL" { + item.Children[i].Content = []byte(changedURL) } - t.Logf("test unmarshal %s", Marshal(item)) - break } + t.Logf("test unmarshal %s", Marshal(item)) + if err := Unmarshal(item, &v); err != nil { t.Fatal(err) } diff --git a/xsd/parse.go b/xsd/parse.go index 148e7095..01a3c423 100644 --- a/xsd/parse.go +++ b/xsd/parse.go @@ -1068,11 +1068,10 @@ func parseMinMaxRestriction(el *xmltree.Element, base Type) (time.Time, float64) // The base of the linked type is unknown, try to parse dates and decimals d, err := time.Parse("2006-01-02", el.Attr("", "value")) if err != nil { - d, err := time.Parse(time.RFC3339, el.Attr("", "value")) + d, err = time.Parse(time.RFC3339, el.Attr("", "value")) if err != nil { decimal = parseDecimal(el.Attr("", "value")) } - date = d } date = d } else { diff --git a/xsd/xsd.go b/xsd/xsd.go index 9ff6bc48..952082f7 100644 --- a/xsd/xsd.go +++ b/xsd/xsd.go @@ -282,7 +282,7 @@ Loop: case xml.EndElement: break Loop case xml.StartElement: - if (tok.Name != xml.Name{schemaNS, "documentation"}) { + if (tok.Name != xml.Name{Space: schemaNS, Local: "documentation"}) { if err := d.Skip(); err != nil { return err } diff --git a/xsdgen/cli.go b/xsdgen/cli.go index cfc21ac4..b7d95bef 100644 --- a/xsdgen/cli.go +++ b/xsdgen/cli.go @@ -84,7 +84,7 @@ func (cfg *Config) ReadFiles(files ...string) ([][]byte, error) { if err != nil { return nil, err } - cfg.debugf("read %s(%s)", path, filename) + cfg.debugf("read %s (%s)", path, filename) cfg.FilesRead[filename] = true if cfg.followImports { dir := filepath.Dir(path) @@ -94,6 +94,10 @@ func (cfg *Config) ReadFiles(files ...string) ([][]byte, error) { } importedFiles := make([]string, 0, len(importedRefs)) for _, r := range importedRefs { + if r.Location == "" { + continue + } + if filepath.IsAbs(r.Location) { importedFiles = append(importedFiles, r.Location) } else { @@ -104,10 +108,9 @@ func (cfg *Config) ReadFiles(files ...string) ([][]byte, error) { if err != nil { return nil, fmt.Errorf("error reading imported files: %v", err) } - for _, d := range referencedData { - // prepend imported refs (i.e. append before the referencing file) - data = append(data, d) - } + + // prepend imported refs (i.e. append before the referencing file) + data = append(data, referencedData...) } data = append(data, b) } @@ -153,7 +156,7 @@ func (cfg *Config) GenCLI(arguments ...string) error { return err } if fs.NArg() == 0 { - return errors.New("Usage: xsdgen [-ns xmlns] [-r rule] [-o file] [-pkg pkg] file ...") + return errors.New("usage: xsdgen [-ns xmlns] [-r rule] [-o file] [-pkg pkg] file ... ") } if *debug { cfg.Option(LogLevel(5)) diff --git a/xsdgen/config.go b/xsdgen/config.go index 93a1063f..151f8d48 100644 --- a/xsdgen/config.go +++ b/xsdgen/config.go @@ -566,7 +566,7 @@ func (cfg *Config) public(name xml.Name) string { // // XML Schema is wonderful, aint it? func (cfg *Config) parseSOAPArrayType(s xsd.Schema, t xsd.Type) xsd.Type { - const soapenc = "http://schemas.xmlsoap.org/soap/encoding/" + // const soapenc = "http://schemas.xmlsoap.org/soap/encoding/" const wsdl = "http://schemas.xmlsoap.org/wsdl/" var itemType xml.Name @@ -856,7 +856,7 @@ func (cfg *Config) soapArrayToSlice(s spec) spec { } else { unmarshalFn = unmarshalFn.Body(` var tok xml.Token - var itemTag = xml.Name{%q, %q} + var itemTag = xml.Name{Space: %q, Local: %q} for tok, err = d.Token(); err == nil; tok, err = d.Token() { if tok, ok := tok.(xml.StartElement); ok { @@ -885,6 +885,12 @@ func (cfg *Config) soapArrayToSlice(s spec) spec { if xmltag.Local == ",any" { xmltag.Local = "item" } + + space := " " + if xmltag.Space == "" { + space = "" + } + marshal, err := gen.Func("MarshalXML"). Receiver("a "+s.name). Args("e *xml.Encoder", "start xml.StartElement"). @@ -892,16 +898,16 @@ func (cfg *Config) soapArrayToSlice(s spec) spec { Body(` var output struct { ArrayType string `+"`xml:\"http://schemas.xmlsoap.org/wsdl/ arrayType,attr\"`"+` - Items []%[1]s `+"`xml:\"%[2]s %[3]s\"`"+` + Items []%[1]s `+"`xml:\"%[2]s%[3]s%[4]s\"`"+` } output.Items = []%[1]s(a) start.Attr = append(start.Attr, xml.Attr { - Name: xml.Name{"", "xmlns:ns1"}, - Value: %[4]q, + Name: xml.Name{Space: "", Local: "xmlns:ns1"}, + Value: %[5]q, }) - output.ArrayType = "ns1:%[5]s[]" + output.ArrayType = "ns1:%[6]s[]" return e.EncodeElement(&output, start) - `, itemType, xmltag.Space, xmltag.Local, baseType.Space, baseType.Local).Decl() + `, itemType, xmltag.Space, space, xmltag.Local, baseType.Space, baseType.Local).Decl() if err != nil { cfg.logf("error generating MarshalXML method of %s: %v", s.name, err) return s diff --git a/xsdgen/example_test.go b/xsdgen/example_test.go index b5068223..3c9308ea 100644 --- a/xsdgen/example_test.go +++ b/xsdgen/example_test.go @@ -230,10 +230,10 @@ func ExampleSOAPArrayAsSlice() { // func (a BoolArray) MarshalXML(e *xml.Encoder, start xml.StartElement) error { // var output struct { // ArrayType string `xml:"http://schemas.xmlsoap.org/wsdl/ arrayType,attr"` - // Items []bool `xml:" item"` + // Items []bool `xml:"item"` // } // output.Items = []bool(a) - // start.Attr = append(start.Attr, xml.Attr{Name: xml.Name{"", "xmlns:ns1"}, Value: "http://www.w3.org/2001/XMLSchema"}) + // start.Attr = append(start.Attr, xml.Attr{Name: xml.Name{Space: "", Local: "xmlns:ns1"}, Value: "http://www.w3.org/2001/XMLSchema"}) // output.ArrayType = "ns1:boolean[]" // return e.EncodeElement(&output, start) // } diff --git a/xsdgen/xsdgen_test.go b/xsdgen/xsdgen_test.go index b99f20b4..9742c419 100644 --- a/xsdgen/xsdgen_test.go +++ b/xsdgen/xsdgen_test.go @@ -3,6 +3,7 @@ package xsdgen import ( "os" "regexp" + "strings" "testing" ) @@ -21,21 +22,21 @@ func (t *testLogger) Printf(format string, v ...interface{}) { } func TestLibrarySchema(t *testing.T) { - testGen(t, "http://dyomedea.com/ns/library", "testdata/library.xsd") + testGen(t, "-ns http://dyomedea.com/ns/library testdata/library.xsd") } func TestPurchasOrderSchema(t *testing.T) { - testGen(t, "http://www.example.com/PO1", "testdata/po1.xsd") + testGen(t, "-ns http://www.example.com/PO1 testdata/po1.xsd") } func TestUSTreasureSDN(t *testing.T) { - testGen(t, "http://tempuri.org/sdnList.xsd", "testdata/sdn.xsd") + testGen(t, "-ns http://tempuri.org/sdnList.xsd testdata/sdn.xsd") } func TestSoap(t *testing.T) { - testGen(t, "http://schemas.xmlsoap.org/soap/encoding/", "testdata/soap11.xsd") + testGen(t, "-ns http://schemas.xmlsoap.org/soap/encoding/ testdata/soap11.xsd") } func TestSimpleStruct(t *testing.T) { - testGen(t, "http://example.org/ns", "testdata/simple-struct.xsd") + testGen(t, "-ns http://example.org/ns testdata/simple-struct.xsd") } -func testGen(t *testing.T, ns string, files ...string) string { +func testGen(t *testing.T, command string) string { file, err := os.CreateTemp("", "xsdgen") if err != nil { t.Fatal(err) @@ -46,8 +47,7 @@ func testGen(t *testing.T, ns string, files ...string) string { cfg.Option(DefaultOptions...) cfg.Option(LogOutput((*testLogger)(t))) - args := []string{"-v", "-o", file.Name(), "-ns", ns, "-f"} - err = cfg.GenCLI(append(args, files...)...) + err = cfg.GenCLI(append([]string{"-o", file.Name()}, strings.Split(command, " ")...)...) if err != nil { t.Error(err) } @@ -59,7 +59,7 @@ func testGen(t *testing.T, ns string, files ...string) string { } func TestMixedType(t *testing.T) { - data := testGen(t, "http://example.org", "testdata/mixed-complex.xsd") + data := testGen(t, "-ns http://example.org testdata/mixed-complex.xsd") if !grep(`PositiveNumber[^}]*,chardata`, data) { t.Errorf("type decl for PositiveNumber did not contain chardata, got \n%s", data) } else { @@ -68,13 +68,13 @@ func TestMixedType(t *testing.T) { } func TestBase64Binary(t *testing.T) { - t.Logf("%s\n", testGen(t, "http://example.org/", "testdata/base64.xsd")) + t.Logf("%s\n", testGen(t, "-ns http://example.org/ testdata/base64.xsd")) } func TestSimpleUnion(t *testing.T) { - t.Logf("%s\n", testGen(t, "http://example.org/", "testdata/simple-union.xsd")) + t.Logf("%s\n", testGen(t, "-ns http://example.org/ testdata/simple-union.xsd")) } func TestImports(t *testing.T) { - t.Logf("%s\n", testGen(t, "ns1", "testdata/ns1.xsd")) + t.Logf("%s\n", testGen(t, "-f -ns ns1 testdata/ns1.xsd")) } From 5d89239a17cffd6e4c9783a4dbd700899d1f1cb0 Mon Sep 17 00:00:00 2001 From: henryolik <9393124+henryolik@users.noreply.github.com> Date: Thu, 12 Sep 2024 18:09:47 +0200 Subject: [PATCH 4/9] Ignore nil datetime field --- xsdgen/config.go | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/xsdgen/config.go b/xsdgen/config.go index 151f8d48..192be903 100644 --- a/xsdgen/config.go +++ b/xsdgen/config.go @@ -711,7 +711,10 @@ func (cfg *Config) addStandardHelpers() { Receiver("t *"+name). Args("text []byte"). Returns("error"). - Body(`return _unmarshalTime(text, (*time.Time)(t), %q)`, timeSpec). + Body(`if len(text) == 0 { + return nil + } + return _unmarshalTime(text, (*time.Time)(t), %q)`, timeSpec). MustDecl(), gen.Func("MarshalText"). Receiver("t "+name). From 07c570ff9af5d69c78f76f4e04edee19561d46af Mon Sep 17 00:00:00 2001 From: henryolik <9393124+henryolik@users.noreply.github.com> Date: Thu, 12 Sep 2024 18:18:20 +0200 Subject: [PATCH 5/9] Fixed tests --- xsdgen/config.go | 9 +++++---- xsdgen/example_test.go | 3 +++ 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/xsdgen/config.go b/xsdgen/config.go index 192be903..c42c4315 100644 --- a/xsdgen/config.go +++ b/xsdgen/config.go @@ -711,10 +711,11 @@ func (cfg *Config) addStandardHelpers() { Receiver("t *"+name). Args("text []byte"). Returns("error"). - Body(`if len(text) == 0 { - return nil - } - return _unmarshalTime(text, (*time.Time)(t), %q)`, timeSpec). + Body(` + if len(text) == 0 { + return nil + } + return _unmarshalTime(text, (*time.Time)(t), %q)`, timeSpec). MustDecl(), gen.Func("MarshalText"). Receiver("t "+name). diff --git a/xsdgen/example_test.go b/xsdgen/example_test.go index 3c9308ea..37ec65c5 100644 --- a/xsdgen/example_test.go +++ b/xsdgen/example_test.go @@ -324,6 +324,9 @@ func ExampleUseFieldNames() { // type xsdDate time.Time // // func (t *xsdDate) UnmarshalText(text []byte) error { + // if len(text) == 0 { + // return nil + // } // return _unmarshalTime(text, (*time.Time)(t), "2006-01-02") // } // func (t xsdDate) MarshalText() ([]byte, error) { From 06ff7813f3eb04bc6354fc4be534641ce53dca32 Mon Sep 17 00:00:00 2001 From: henryolik <9393124+henryolik@users.noreply.github.com> Date: Tue, 3 Dec 2024 15:34:50 +0100 Subject: [PATCH 6/9] Fixed nil field in pointer unmarshal --- xsdgen/xsdgen.go | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/xsdgen/xsdgen.go b/xsdgen/xsdgen.go index 7c043a74..b73a37a7 100644 --- a/xsdgen/xsdgen.go +++ b/xsdgen/xsdgen.go @@ -941,7 +941,9 @@ func (cfg *Config) genComplexTypeMethods(t *xsd.ComplexType, overrides []fieldOv {{end -}} {{end}} - return d.DecodeElement(&overlay, &start) + err := d.DecodeElement(&overlay, &start) + t.{{.FieldName}} = ({{.FromType}})(overlay.{{.FieldName}}) + return err `, data).Decl() if err != nil { return nil, nil, err From ab2b24e3dd85de15d8b76e29ce5772c9671d0f5b Mon Sep 17 00:00:00 2001 From: henryolik <9393124+henryolik@users.noreply.github.com> Date: Thu, 5 Dec 2024 10:11:44 +0100 Subject: [PATCH 7/9] Fixed unmarshal template --- xsdgen/example_test.go | 3 ++- xsdgen/xsdgen.go | 2 ++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/xsdgen/example_test.go b/xsdgen/example_test.go index 37ec65c5..550dcfed 100644 --- a/xsdgen/example_test.go +++ b/xsdgen/example_test.go @@ -314,7 +314,8 @@ func ExampleUseFieldNames() { // } // overlay.T = (*T)(t) // overlay.Published = (*xsdDate)(&overlay.T.Published) - // return d.DecodeElement(&overlay, &start) + // err := d.DecodeElement(&overlay, &start) + // return err //} // // type Library struct { diff --git a/xsdgen/xsdgen.go b/xsdgen/xsdgen.go index b73a37a7..b86ed01a 100644 --- a/xsdgen/xsdgen.go +++ b/xsdgen/xsdgen.go @@ -942,7 +942,9 @@ func (cfg *Config) genComplexTypeMethods(t *xsd.ComplexType, overrides []fieldOv {{end}} err := d.DecodeElement(&overlay, &start) + {{range .Overrides}}{{if .IsPtr}} t.{{.FieldName}} = ({{.FromType}})(overlay.{{.FieldName}}) + {{end}}{{end}} return err `, data).Decl() if err != nil { From 65caa6f786ef52cc6a58b14be3f294bfb13a580b Mon Sep 17 00:00:00 2001 From: henryolik <9393124+henryolik@users.noreply.github.com> Date: Thu, 5 Dec 2024 10:24:09 +0100 Subject: [PATCH 8/9] Updated deps to latest versions --- go.mod | 15 ++++++++++----- go.sum | 20 ++++++++++++-------- 2 files changed, 22 insertions(+), 13 deletions(-) diff --git a/go.mod b/go.mod index e66cb2ba..9aea17a2 100644 --- a/go.mod +++ b/go.mod @@ -1,11 +1,16 @@ module github.com/nukib/go-xml -go 1.21 +go 1.22.0 + +toolchain go1.22.5 require ( - golang.org/x/net v0.19.0 - golang.org/x/text v0.14.0 - golang.org/x/tools v0.16.0 + golang.org/x/net v0.32.0 + golang.org/x/text v0.21.0 + golang.org/x/tools v0.28.0 ) -require golang.org/x/mod v0.14.0 // indirect +require ( + golang.org/x/mod v0.22.0 // indirect + golang.org/x/sync v0.10.0 // indirect +) diff --git a/go.sum b/go.sum index d3df82f5..6b9a9b32 100644 --- a/go.sum +++ b/go.sum @@ -1,8 +1,12 @@ -golang.org/x/mod v0.14.0 h1:dGoOF9QVLYng8IHTm7BAyWqCqSheQ5pYWGhzW00YJr0= -golang.org/x/mod v0.14.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= -golang.org/x/net v0.19.0 h1:zTwKpTd2XuCqf8huc7Fo2iSy+4RHPd10s4KzeTnVr1c= -golang.org/x/net v0.19.0/go.mod h1:CfAk/cbD4CthTvqiEl8NpboMuiuOYsAr/7NOjZJtv1U= -golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= -golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= -golang.org/x/tools v0.16.0 h1:GO788SKMRunPIBCXiQyo2AaexLstOrVhuAL5YwsckQM= -golang.org/x/tools v0.16.0/go.mod h1:kYVVN6I1mBNoB1OX+noeBjbRk4IUEPa7JJ+TJMEooJ0= +github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= +github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +golang.org/x/mod v0.22.0 h1:D4nJWe9zXqHOmWqj4VMOJhvzj7bEZg4wEYa759z1pH4= +golang.org/x/mod v0.22.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY= +golang.org/x/net v0.32.0 h1:ZqPmj8Kzc+Y6e0+skZsuACbx+wzMgo5MQsJh9Qd6aYI= +golang.org/x/net v0.32.0/go.mod h1:CwU0IoeOlnQQWJ6ioyFrfRuomB8GKF6KbYXZVyeXNfs= +golang.org/x/sync v0.10.0 h1:3NQrjDixjgGwUOCaF8w2+VYHv0Ve/vGYSbdkTa98gmQ= +golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo= +golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ= +golang.org/x/tools v0.28.0 h1:WuB6qZ4RPCQo5aP3WdKZS7i595EdWqWR8vqJTlwTVK8= +golang.org/x/tools v0.28.0/go.mod h1:dcIOrVd3mfQKTgrDVQHqCPMWy6lnhfhtX3hLXYVLfRw= From 23337029f811aca9a6165e091fd28f5a26acf3c0 Mon Sep 17 00:00:00 2001 From: henryolik <9393124+henryolik@users.noreply.github.com> Date: Thu, 5 Dec 2024 10:46:51 +0100 Subject: [PATCH 9/9] Fixed incorrect unmarshal type --- xsdgen/xsdgen.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xsdgen/xsdgen.go b/xsdgen/xsdgen.go index b86ed01a..f4d76f54 100644 --- a/xsdgen/xsdgen.go +++ b/xsdgen/xsdgen.go @@ -943,7 +943,7 @@ func (cfg *Config) genComplexTypeMethods(t *xsd.ComplexType, overrides []fieldOv err := d.DecodeElement(&overlay, &start) {{range .Overrides}}{{if .IsPtr}} - t.{{.FieldName}} = ({{.FromType}})(overlay.{{.FieldName}}) + t.{{.FieldName}} = (*{{.FromType}})(overlay.{{.FieldName}}) {{end}}{{end}} return err `, data).Decl()