forked from droyo/go-xml
-
Notifications
You must be signed in to change notification settings - Fork 1
/
cli.go
119 lines (110 loc) · 3.29 KB
/
cli.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
package xsdgen
import (
"errors"
"flag"
"fmt"
"go/ast"
"io/ioutil"
"aqwari.net/xml/internal/commandline"
"aqwari.net/xml/internal/gen"
"aqwari.net/xml/xsd"
)
// GenCode reads all xml schema definitions from the provided
// data. If succesful, 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 {
cfg.debugf("setting namespaces to %s", cfg.namespaces)
cfg.Option(Namespaces(lookupTargetNS(data...)...))
}
deps, err := xsd.Parse(data...)
if err != nil {
return nil, err
}
primaries := make([]xsd.Schema, 0, len(cfg.namespaces))
for _, s := range deps {
for _, ns := range cfg.namespaces {
if s.TargetNS == ns {
primaries = append(primaries, s)
break
}
}
}
if len(primaries) < len(cfg.namespaces) {
return nil, fmt.Errorf("could not find schema for all namespaces in %s",
cfg.namespaces)
}
cfg.addStandardHelpers()
return cfg.gen(primaries, deps)
}
// 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) {
data := make([][]byte, 0, len(files))
for _, filename := range files {
b, err := ioutil.ReadFile(filename)
if err != nil {
return nil, err
}
cfg.debugf("read %s", filename)
data = append(data, b)
}
code, err := cfg.GenCode(data...)
if err != nil {
return nil, err
}
return code.GenAST()
}
// The GenSource method converts the AST returned by GenAST to formatted
// Go source code.
func (cfg *Config) GenSource(files ...string) ([]byte, error) {
file, err := cfg.GenAST(files...)
if err != nil {
return nil, err
}
return gen.FormattedSource(file)
}
// GenCLI creates a file containing Go source generated from an XML
// Schema. Main is meant to be called as part of a command, and can
// be used to change the behavior of the xsdgen command in ways that
// its command-line arguments do not allow. The arguments are the
// same as those passed to the xsdgen command.
func (cfg *Config) GenCLI(arguments ...string) error {
var (
err error
replaceRules commandline.ReplaceRuleList
xmlns commandline.Strings
fs = flag.NewFlagSet("xsdgen", flag.ExitOnError)
packageName = fs.String("pkg", "", "name of the the generated package")
output = fs.String("o", "xsdgen_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(&xmlns, "ns", "target namespace(s) to generate types for")
fs.Parse(arguments)
if fs.NArg() == 0 {
return errors.New("Usage: xsdgen [-ns xmlns] [-r rule] [-o file] [-pkg pkg] file ...")
}
if *debug {
cfg.Option(LogLevel(5))
} else if *verbose {
cfg.Option(LogLevel(1))
}
cfg.Option(Namespaces(xmlns...))
for _, r := range replaceRules {
cfg.Option(replaceAllNamesRegex(r.From, r.To))
}
if *packageName != "" {
cfg.Option(PackageName(*packageName))
}
file, err := cfg.GenAST(fs.Args()...)
if err != nil {
return err
}
data, err := gen.FormattedSource(file)
if err != nil {
return err
}
return ioutil.WriteFile(*output, data, 0666)
}