diff --git a/xsd/parse.go b/xsd/parse.go
index 0e1ac4f..c087aaf 100644
--- a/xsd/parse.go
+++ b/xsd/parse.go
@@ -146,7 +146,10 @@ func Parse(docs ...[]byte) ([]Schema, error) {
for _, root := range schema {
tns := root.Attr("", "targetNamespace")
- s := Schema{TargetNS: tns, Types: make(map[xml.Name]Type)}
+ efd := parseForm(root.Attr("", "elementFormDefault"), FormOptionUndefined)
+ afd := parseForm(root.Attr("", "attributeFormDefault"), FormOptionUndefined)
+
+ s := Schema{TargetNS: tns, ElementFormDefault: efd, AttributeFormDefault: afd, Types: make(map[xml.Name]Type)}
if err := s.parse(root); err != nil {
return nil, err
}
@@ -404,7 +407,7 @@ func deref(ref, real *xmltree.Element) *xmltree.Element {
el := new(xmltree.Element)
el.Scope = ref.Scope
el.Name = real.Name
- el.StartElement.Attr = append([]xml.Attr{}, real.StartElement.Attr...)
+ el.StartElement.Attr = []xml.Attr{}
el.Content = append([]byte{}, real.Content...)
el.Children = append([]xmltree.Element{}, real.Children...)
@@ -413,11 +416,17 @@ func deref(ref, real *xmltree.Element) *xmltree.Element {
hasQName := map[xml.Name]bool{
xml.Name{"", "type"}: true,
}
- for i, attr := range el.StartElement.Attr {
+ // Some attribute should not be copied
+ dontCopy := map[xml.Name]bool{
+ xml.Name{"", "name"}: true,
+ xml.Name{"", "form"}: true,
+ }
+ for _, attr := range real.StartElement.Attr {
if hasQName[attr.Name] {
xmlname := real.Resolve(attr.Value)
- attr.Value = ref.Prefix(xmlname)
- el.StartElement.Attr[i] = attr
+ el.SetAttr(attr.Name.Space, attr.Name.Local, ref.Prefix(xmlname))
+ } else if !dontCopy[attr.Name] {
+ el.SetAttr(attr.Name.Space, attr.Name.Local, attr.Value)
}
}
// If there are child elements, rather than checking all children
@@ -429,11 +438,16 @@ func deref(ref, real *xmltree.Element) *xmltree.Element {
// Attributes added to the reference overwrite attributes in the
// referenced element.
for _, attr := range ref.StartElement.Attr {
- if (attr.Name != xml.Name{"", "ref"}) {
+ if (attr.Name == xml.Name{"", "ref"}) {
+ el.SetAttr("", "name", attr.Value)
+ } else {
el.SetAttr(attr.Name.Space, attr.Name.Local, attr.Value)
}
}
+ // Referenced elements are always qualified
+ el.SetAttr("", "form", "qualified")
+
return el
}
@@ -582,9 +596,10 @@ func attributeDefaultType(root *xmltree.Element) {
var (
isAttr = isElem(schemaNS, "attribute")
hasNoType = hasAttrValue("", "type", "")
+ hasNoRef = hasAttrValue("", "ref", "")
anyType = xml.Name{Space: schemaNS, Local: "anySimpleType"}
)
- for _, el := range root.SearchFunc(and(isAttr, hasNoType)) {
+ for _, el := range root.SearchFunc(and(isAttr, hasNoType, hasNoRef)) {
el.SetAttr("", "type", el.Prefix(anyType))
}
}
@@ -598,9 +613,10 @@ func elementDefaultType(root *xmltree.Element) {
var (
isElement = isElem(schemaNS, "element")
hasNoType = hasAttrValue("", "type", "")
+ hasNoRef = hasAttrValue("", "ref", "")
anyType = xml.Name{Space: schemaNS, Local: "anyType"}
)
- for _, el := range root.SearchFunc(and(isElement, hasNoType)) {
+ for _, el := range root.SearchFunc(and(isElement, hasNoType, hasNoRef)) {
el.SetAttr("", "type", el.Prefix(anyType))
}
}
@@ -658,9 +674,9 @@ func (s *Schema) parseComplexType(root *xmltree.Element) *ComplexType {
case "annotation":
doc = doc.append(parseAnnotation(el))
case "simpleContent":
- t.parseSimpleContent(s.TargetNS, el)
+ t.parseSimpleContent(s.TargetNS, s.AttributeFormDefault, el)
case "complexContent":
- t.parseComplexContent(s.TargetNS, el)
+ t.parseComplexContent(s.TargetNS, s.ElementFormDefault, s.AttributeFormDefault, el)
default:
stop("unexpected element " + el.Name.Local)
}
@@ -671,7 +687,7 @@ func (s *Schema) parseComplexType(root *xmltree.Element) *ComplexType {
// simpleContent indicates that the content model of the new type
// contains only character data and no elements
-func (t *ComplexType) parseSimpleContent(ns string, root *xmltree.Element) {
+func (t *ComplexType) parseSimpleContent(ns string, afd FormOption, root *xmltree.Element) {
var doc annotation
t.Mixed = true
@@ -685,7 +701,7 @@ func (t *ComplexType) parseSimpleContent(ns string, root *xmltree.Element) {
t.Base = parseType(el.Resolve(el.Attr("", "base")))
t.Extends = true
for _, v := range el.Search(schemaNS, "attribute") {
- t.Attributes = append(t.Attributes, parseAttribute(ns, v))
+ t.Attributes = append(t.Attributes, parseAttribute(ns, afd, v))
}
}
})
@@ -694,7 +710,7 @@ func (t *ComplexType) parseSimpleContent(ns string, root *xmltree.Element) {
// The complexContent element signals that we intend to restrict or extend
// the content model of a complex type.
-func (t *ComplexType) parseComplexContent(ns string, root *xmltree.Element) {
+func (t *ComplexType) parseComplexContent(ns string, efd FormOption, afd FormOption, root *xmltree.Element) {
var doc annotation
if mixed := root.Attr("", "mixed"); mixed != "" {
t.Mixed = parseBool(mixed)
@@ -714,7 +730,7 @@ func (t *ComplexType) parseComplexContent(ns string, root *xmltree.Element) {
usedElt := make(map[xml.Name]int)
for _, v := range el.Search(schemaNS, "element") {
- elt := parseElement(ns, v)
+ elt := parseElement(ns, efd, afd, v)
if existing, ok := usedElt[elt.Name]; !ok {
usedElt[elt.Name] = len(t.Elements)
t.Elements = append(t.Elements, elt)
@@ -724,7 +740,7 @@ func (t *ComplexType) parseComplexContent(ns string, root *xmltree.Element) {
}
for _, v := range el.Search(schemaNS, "attribute") {
- t.Attributes = append(t.Attributes, parseAttribute(ns, v))
+ t.Attributes = append(t.Attributes, parseAttribute(ns, afd, v))
}
case "annotation":
doc = doc.append(parseAnnotation(el))
@@ -814,10 +830,11 @@ func parseAnyElement(ns string, el *xmltree.Element) Element {
}
}
-func parseElement(ns string, el *xmltree.Element) Element {
+func parseElement(ns string, efd FormOption, afd FormOption, el *xmltree.Element) Element {
var doc annotation
e := Element{
Name: el.ResolveDefault(el.Attr("", "name"), ns),
+ Form: parseForm(el.Attr("", "form"), efd),
Type: parseType(el.Resolve(el.Attr("", "type"))),
Default: el.Attr("", "default"),
Abstract: parseBool(el.Attr("", "abstract")),
@@ -838,16 +855,12 @@ func parseElement(ns string, el *xmltree.Element) Element {
doc = doc.append(parseAnnotation(el))
}
})
- t, ok := e.Type.(linkedType)
- if ok {
- e.Name.Space = t.Space
- }
e.Doc = string(doc)
e.Attr = el.StartElement.Attr
return e
}
-func parseAttribute(ns string, el *xmltree.Element) Attribute {
+func parseAttribute(ns string, afd FormOption, el *xmltree.Element) Attribute {
var a Attribute
var doc annotation
// Non-QName xml attributes explicitly do *not* have a namespace.
@@ -855,8 +868,9 @@ func parseAttribute(ns string, el *xmltree.Element) Attribute {
a.Name = el.Resolve(el.Attr("", "name"))
} else {
a.Name.Local = name
+ a.Name.Space = ns
}
- a.Name.Space = ns
+ a.Form = parseForm(el.Attr("", "form"), afd)
a.Type = parseType(el.Resolve(el.Attr("", "type")))
a.Default = el.Attr("", "default")
a.Scope = el.Scope
@@ -1107,3 +1121,15 @@ func (s *Schema) lookupType(name linkedType, ext map[xml.Name]Type) (Type, bool)
v, ok := s.Types[xml.Name(name)]
return v, ok
}
+
+func parseForm(s string, d FormOption) FormOption {
+ s = strings.TrimSpace(s)
+ form := FormOption(s)
+
+ if form == FormOptionUndefined {
+ return d
+ } else {
+ return form
+ }
+
+}
diff --git a/xsd/testdata/AttributeGroup.xsd b/xsd/testdata/AttributeGroup.xsd
index 147cfa4..49a8e58 100644
--- a/xsd/testdata/AttributeGroup.xsd
+++ b/xsd/testdata/AttributeGroup.xsd
@@ -9,7 +9,7 @@
-
+
-
+
diff --git a/xsd/testdata/ComplexType.json b/xsd/testdata/ComplexType.json
index 33e2e3c..18a397e 100644
--- a/xsd/testdata/ComplexType.json
+++ b/xsd/testdata/ComplexType.json
@@ -1,27 +1,27 @@
{
"CustomerType": {
"Elements": [
- {"Name": {"Local": "CompanyName"}, "Type": 38},
- {"Name": {"Local": "ContactName"}, "Type": 38},
- {"Name": {"Local": "ContactTitle"}, "Type": 38},
- {"Name": {"Local": "Phone"}, "Type": 38},
- {"Name": {"Local": "Fax"}, "Type": 38},
+ {"Name": {"Local": "CompanyName", "Space": "tns"}, "Type": 38},
+ {"Name": {"Local": "ContactName", "Space": "tns"}, "Type": 38},
+ {"Name": {"Local": "ContactTitle", "Space": "tns"}, "Type": 38},
+ {"Name": {"Local": "Phone", "Space": "tns"}, "Type": 38},
+ {"Name": {"Local": "Fax", "Space": "tns"}, "Type": 38},
{
- "Name": {"Local": "FullAddress"},
+ "Name": {"Local": "FullAddress", "Space": "tns"},
"Type": {
"Elements": [
- {"Name": {"Local": "Address"}, "Type": 38},
- {"Name": {"Local": "City"}, "Type": 38},
- {"Name": {"Local": "Region"}, "Type": 38},
- {"Name": {"Local": "PostalCode"}, "Type": 38},
- {"Name": {"Local": "Country"}, "Type": 38}
+ {"Name": {"Local": "Address", "Space": "tns"}, "Type": 38},
+ {"Name": {"Local": "City", "Space": "tns"}, "Type": 38},
+ {"Name": {"Local": "Region", "Space": "tns"}, "Type": 38},
+ {"Name": {"Local": "PostalCode", "Space": "tns"}, "Type": 38},
+ {"Name": {"Local": "Country", "Space": "tns"}, "Type": 38}
],
- "Attributes": [{"Name": {"Local": "CustomerID"}, "Type": 40}]
+ "Attributes": [{"Name": {"Local": "CustomerID", "Space": "tns"}, "Type": 40}]
}
}
],
"Attributes": [
- {"Name": {"Local": "CustomerID"}, "Type": 40}
+ {"Name": {"Local": "CustomerID", "Space": "tns"}, "Type": 40}
]
}
}
diff --git a/xsd/testdata/ComplexType.xsd b/xsd/testdata/ComplexType.xsd
index dcf9ce8..6d034cc 100644
--- a/xsd/testdata/ComplexType.xsd
+++ b/xsd/testdata/ComplexType.xsd
@@ -5,13 +5,13 @@
-
+
-
-
+
+
@@ -21,4 +21,3 @@
-
diff --git a/xsd/xsd.go b/xsd/xsd.go
index fb84c36..0f11f09 100644
--- a/xsd/xsd.go
+++ b/xsd/xsd.go
@@ -49,6 +49,8 @@ type Element struct {
Doc string
// The canonical name of this element
Name xml.Name
+ // What form of the naming to expect
+ Form FormOption
// True if this element can have any name. See
// http://www.w3.org/TR/2004/REC-xmlschema-1-20041028/structures.html#element-any
Wildcard bool
@@ -80,6 +82,8 @@ type Attribute struct {
// The canonical name of this attribute. It is uncommon for attributes
// to have a name space.
Name xml.Name
+ // What form of the naming to expect
+ Form FormOption
// Annotation provided for this attribute by the schema author.
Doc string
// The type of the attribute value. Must be a simple or built-in Type.
@@ -103,6 +107,10 @@ type Schema struct {
// The Target namespace of the schema. All types defined in this
// schema will be in this name space.
TargetNS string `xml:"targetNamespace,attr"`
+ // ElementFormDefault
+ ElementFormDefault FormOption `xml:"elementFormDefault,attr,omitempty"`
+ // AttributeFormDefault
+ AttributeFormDefault FormOption `xml:"attributeFormDefault,attr,omitempty"`
// Types defined in this schema declaration
Types map[xml.Name]Type
// Any annotations declared at the top-level of the schema, separated
@@ -329,3 +337,11 @@ var StandardSchema = [][]byte{
wsdl2003xsd, // http://schemas.xmlsoap.org/wsdl/
xlinkxsd, // http://www.w3.org/1999/xlink
}
+
+type FormOption string
+
+const (
+ FormOptionUndefined FormOption = ""
+ FormOptionUnqualified FormOption = "unqualified"
+ FormOptionQualified FormOption = "qualified"
+)
diff --git a/xsd/xsd_test.go b/xsd/xsd_test.go
index f79ecb6..060f07d 100644
--- a/xsd/xsd_test.go
+++ b/xsd/xsd_test.go
@@ -131,6 +131,7 @@ func testCompare(t *testing.T, prefix []string, got, want interface{}) bool {
}
if got != want {
t.Errorf("%s: got %#v, wanted %#v", path, got, want)
+ return false
}
return true
}
diff --git a/xsdgen/cli.go b/xsdgen/cli.go
index 0274086..3cdf641 100644
--- a/xsdgen/cli.go
+++ b/xsdgen/cli.go
@@ -6,6 +6,7 @@ import (
"fmt"
"go/ast"
"io/ioutil"
+ "path/filepath"
"strings"
"aqwari.net/xml/internal/commandline"
@@ -62,22 +63,31 @@ 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 {
- b, err := ioutil.ReadFile(filename)
+ path, err := filepath.Abs(filename)
if err != nil {
return nil, err
}
- cfg.debugf("read %s", filename)
+ b, err := ioutil.ReadFile(path)
+ if err != nil {
+ return nil, err
+ }
+ cfg.debugf("read %s(%s)", path, filename)
if cfg.followImports {
+ dir := filepath.Dir(path)
importedRefs, err := xsd.Imports(b)
if err != nil {
return nil, fmt.Errorf("error discovering imports: %v", err)
}
importedFiles := make([]string, 0, len(importedRefs))
for _, r := range importedRefs {
- importedFiles = append(importedFiles, r.Location)
+ if filepath.IsAbs(r.Location) {
+ importedFiles = append(importedFiles, r.Location)
+ } else {
+ importedFiles = append(importedFiles, filepath.Join(dir, r.Location))
+ }
}
referencedData, err := cfg.readFiles(importedFiles...)
if err != nil {
@@ -110,15 +120,16 @@ func (cfg *Config) GenSource(files ...string) ([]byte, error) {
// 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")
- followImports = fs.Bool("f", false, "follow import statements; load imported references recursively into scope")
- verbose = fs.Bool("v", false, "print verbose output")
- debug = fs.Bool("vv", false, "print debug output")
+ 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")
+ followImports = fs.Bool("f", false, "follow import statements; load imported references recursively into scope")
+ targetNamespacesOnly = fs.Bool("t", false, "restict output of types to these declared in the target namespace(s) provided")
+ 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")
@@ -136,6 +147,7 @@ func (cfg *Config) GenCLI(arguments ...string) error {
}
cfg.Option(Namespaces(xmlns...))
cfg.Option(FollowImports(*followImports))
+ cfg.Option(TargetNamespacesOnly(*targetNamespacesOnly))
for _, r := range replaceRules {
cfg.Option(replaceAllNamesRegex(r.From, r.To))
}
diff --git a/xsdgen/config.go b/xsdgen/config.go
index a2bf601..9d8cbe1 100644
--- a/xsdgen/config.go
+++ b/xsdgen/config.go
@@ -21,9 +21,10 @@ type Config struct {
namespaces []string
pkgname string
// load xsd imports recursively into memory before parsing
- followImports bool
- preprocessType typeTransform
- postprocessType specTransform
+ followImports bool
+ targetNamespacesOnly bool
+ preprocessType typeTransform
+ postprocessType specTransform
// Helper functions
helperFuncs map[string]*ast.FuncDecl
helperTypes map[xml.Name]spec
@@ -247,6 +248,18 @@ func FollowImports(follow bool) Option {
}
}
+// TargetNamespacesOnly specifies whether or
+// not to filter
+// to recursively read in imported schemas
+// before attempting to parse
+func TargetNamespacesOnly(tnsOnly bool) Option {
+ return func(cfg *Config) Option {
+ prev := cfg.targetNamespacesOnly
+ cfg.targetNamespacesOnly = tnsOnly
+ return TargetNamespacesOnly(prev)
+ }
+}
+
// Replace allows for substitution rules for all identifiers to
// be specified. If an invalid regular expression is called, no action
// is taken. The Replace option is additive; subsitutions will be
diff --git a/xsdgen/example_test.go b/xsdgen/example_test.go
index 3e3e004..7948407 100644
--- a/xsdgen/example_test.go
+++ b/xsdgen/example_test.go
@@ -109,8 +109,8 @@ func ExampleIgnoreElements() {
// package ws
//
// type Person struct {
- // Name string `xml:"http://www.example.com/ name"`
- // Deceased bool `xml:"http://schemas.xmlsoap.org/soap/encoding/ deceased"`
+ // Name string `xml:"name"`
+ // Deceased bool `xml:"deceased"`
// }
}
@@ -135,7 +135,7 @@ func ExamplePackageName() {
//
// package postal
//
- // // May be no more than 10 items long
+ // // Must be exactly 10 items long
// type Zipcode string
}
@@ -190,7 +190,7 @@ func ExampleHandleSOAPArrayType() {
//
// type BoolArray struct {
// Items []bool `xml:",any"`
- // Offset string `xml:"offset,attr,omitempty"`
+ // Offset string `xml:"http://schemas.xmlsoap.org/soap/encoding/ offset,attr,omitempty"`
// Id string `xml:"id,attr,omitempty"`
// Href string `xml:"href,attr,omitempty"`
// }
@@ -291,34 +291,34 @@ func ExampleUseFieldNames() {
// )
//
// type Book struct {
- // Title string `xml:"http://www.example.com/ title"`
- // Published time.Time `xml:"http://www.example.com/ published"`
- // Author string `xml:"http://www.example.com/ author"`
+ // Title string `xml:"title"`
+ // Published time.Time `xml:"published"`
+ // Author string `xml:"author"`
// }
//
- // func (t *Book) MarshalXML(e *xml.Encoder, start xml.StartElement) error {
- // type T Book
- // var layout struct {
- // *T
- // Published *xsdDate `xml:"http://www.example.com/ published"`
- // }
- // layout.T = (*T)(t)
- // layout.Published = (*xsdDate)(&layout.T.Published)
- // return e.EncodeElement(layout, start)
- // }
- // func (t *Book) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
- // type T Book
- // var overlay struct {
- // *T
- // Published *xsdDate `xml:"http://www.example.com/ published"`
- // }
- // overlay.T = (*T)(t)
- // overlay.Published = (*xsdDate)(&overlay.T.Published)
- // return d.DecodeElement(&overlay, &start)
- // }
+ //func (t *Book) MarshalXML(e *xml.Encoder, start xml.StartElement) error {
+ // type T Book
+ // var layout struct {
+ // *T
+ // Published *xsdDate `xml:"published"`
+ // }
+ // layout.T = (*T)(t)
+ // layout.Published = (*xsdDate)(&layout.T.Published)
+ // return e.EncodeElement(layout, start)
+ //}
+ //func (t *Book) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
+ // type T Book
+ // var overlay struct {
+ // *T
+ // Published *xsdDate `xml:"published"`
+ // }
+ // overlay.T = (*T)(t)
+ // overlay.Published = (*xsdDate)(&overlay.T.Published)
+ // return d.DecodeElement(&overlay, &start)
+ //}
//
// type Library struct {
- // Book []Book `xml:"http://www.example.com/ book"`
+ // Book []Book `xml:"book"`
// }
//
// type xsdDate time.Time
diff --git a/xsdgen/testdata/common.xsd b/xsdgen/testdata/common.xsd
new file mode 100644
index 0000000..1b1e63e
--- /dev/null
+++ b/xsdgen/testdata/common.xsd
@@ -0,0 +1,14 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/xsdgen/testdata/ns1.xsd b/xsdgen/testdata/ns1.xsd
new file mode 100644
index 0000000..5007ecb
--- /dev/null
+++ b/xsdgen/testdata/ns1.xsd
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/xsdgen/testdata/ns2.xsd b/xsdgen/testdata/ns2.xsd
new file mode 100644
index 0000000..b3502b3
--- /dev/null
+++ b/xsdgen/testdata/ns2.xsd
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/xsdgen/xsdgen.go b/xsdgen/xsdgen.go
index 0604c4d..f3fbce4 100644
--- a/xsdgen/xsdgen.go
+++ b/xsdgen/xsdgen.go
@@ -463,6 +463,10 @@ func (cfg *Config) flatten1(t xsd.Type, push func(xsd.Type), depth int) xsd.Type
t.Doc = "Must be at least " + strconv.Itoa(t.Restriction.MinLength) + " items long"
return t
}
+ if t.Restriction.Length != 0 {
+ t.Doc = "Must be exactly " + strconv.Itoa(t.Restriction.Length) + " items long"
+ return t
+ }
return t.Base
case *xsd.ComplexType:
// We can "unpack" a struct if it is extending a simple
@@ -524,7 +528,21 @@ func (cfg *Config) flatten1(t xsd.Type, push func(xsd.Type), depth int) xsd.Type
func (cfg *Config) genTypeSpec(t xsd.Type) (result []spec, err error) {
var s []spec
- cfg.debugf("generating type spec for %q", xsd.XMLName(t).Local)
+
+ name := xsd.XMLName(t)
+ if cfg.targetNamespacesOnly {
+ found := false
+ for _, ns := range cfg.namespaces {
+ if ns == name.Space {
+ found = true
+ }
+ }
+ if !found {
+ return result, nil
+ }
+ }
+
+ cfg.debugf("generating type spec for %q", name.Local)
switch t := t.(type) {
case *xsd.SimpleType:
@@ -534,7 +552,7 @@ func (cfg *Config) genTypeSpec(t xsd.Type) (result []spec, err error) {
case xsd.Builtin:
// pass
default:
- cfg.logf("unexpected %T %s", t, xsd.XMLName(t).Local)
+ cfg.logf("unexpected %T %s", t, name.Local)
}
if err != nil || s == nil {
return result, err
@@ -684,7 +702,14 @@ func (cfg *Config) genComplexType(t *xsd.ComplexType) ([]spec, error) {
if el.Nillable || el.Optional {
options = ",omitempty"
}
- tag := fmt.Sprintf(`xml:"%s %s%s"`, el.Name.Space, el.Name.Local, options)
+
+ tag := ""
+ if el.Form == xsd.FormOptionQualified || t.Name.Space != el.Name.Space {
+ tag = fmt.Sprintf(`xml:"%s %s%s"`, el.Name.Space, el.Name.Local, options)
+ } else {
+ tag = fmt.Sprintf(`xml:"%s%s"`, el.Name.Local, options)
+ }
+
base, err := cfg.expr(el.Type)
if err != nil {
return nil, fmt.Errorf("%s element %s: %v", t.Name.Local, el.Name.Local, err)
@@ -731,14 +756,8 @@ func (cfg *Config) genComplexType(t *xsd.ComplexType) ([]spec, error) {
if attr.Optional {
options = ",omitempty"
}
- qualified := false
- for _, attrAttr := range attr.Attr {
- if attrAttr.Name.Space == "" && attrAttr.Name.Local == "form" && attrAttr.Value == "qualified" {
- qualified = true
- }
- }
var tag string
- if qualified {
+ if attr.Form == xsd.FormOptionQualified {
tag = fmt.Sprintf(`xml:"%s %s,attr%s"`, attr.Name.Space, attr.Name.Local, options)
} else {
tag = fmt.Sprintf(`xml:"%s,attr%s"`, attr.Name.Local, options)
diff --git a/xsdgen/xsdgen_test.go b/xsdgen/xsdgen_test.go
index d206de7..118bde3 100644
--- a/xsdgen/xsdgen_test.go
+++ b/xsdgen/xsdgen_test.go
@@ -47,7 +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}
+ args := []string{"-v", "-o", file.Name(), "-ns", ns, "-f"}
err = cfg.GenCLI(append(args, files...)...)
if err != nil {
t.Error(err)
@@ -75,3 +75,7 @@ func TestBase64Binary(t *testing.T) {
func TestSimpleUnion(t *testing.T) {
t.Logf("%s\n", testGen(t, "http://example.org/", "testdata/simple-union.xsd"))
}
+
+func TestImports(t *testing.T) {
+ t.Logf("%s\n", testGen(t, "ns1", "testdata/ns1.xsd"))
+}