Skip to content

add XMLName field to generated structs #142

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 1 commit into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 28 additions & 0 deletions xsdgen/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -740,11 +740,23 @@ func (cfg *Config) soapArrayToSlice(s spec) spec {
if !ok {
return s
}
var nameField *ast.Field
if len(str.Fields.List) == 2 {
// we can ignore the XMLName field
if ident, ok := str.Fields.List[0].Type.(*ast.Ident); ok && ident.Name == "xml.Name" {
nameField = str.Fields.List[0]
str.Fields.List = str.Fields.List[1:]
}
}
if len(str.Fields.List) != 1 {
return s
}
slice, ok := str.Fields.List[0].Type.(*ast.ArrayType)
if !ok {
// add back the name field if we removed it in the previous step
if nameField != nil {
str.Fields.List = append([]*ast.Field{nameField}, str.Fields.List...)
}
return s
}

Expand All @@ -753,6 +765,10 @@ func (cfg *Config) soapArrayToSlice(s spec) spec {
// element in the array with the appropriate type.
complex, ok := s.xsdType.(*xsd.ComplexType)
if !ok {
// add back the name field if we removed it in the previous step
if nameField != nil {
str.Fields.List = append([]*ast.Field{nameField}, str.Fields.List...)
}
return s
}

Expand All @@ -764,6 +780,10 @@ func (cfg *Config) soapArrayToSlice(s spec) spec {
}

if baseType.Space == "" && baseType.Local == "" {
// add back the name field if we removed it in the previous step
if nameField != nil {
str.Fields.List = append([]*ast.Field{nameField}, str.Fields.List...)
}
return s
}
cfg.debugf("flattening single-element slice struct type %s to []%v", s.name, slice.Elt)
Expand Down Expand Up @@ -831,6 +851,10 @@ func (cfg *Config) soapArrayToSlice(s spec) spec {
unmarshal, err := unmarshalFn.Decl()
if err != nil {
cfg.logf("error generating UnmarshalXML method of %s: %v", s.name, err)
// add back the name field if we removed it in the previous step
if nameField != nil {
str.Fields.List = append([]*ast.Field{nameField}, str.Fields.List...)
}
return s
}

Expand All @@ -856,6 +880,10 @@ func (cfg *Config) soapArrayToSlice(s spec) spec {
`, itemType, xmltag.Space, xmltag.Local, baseType.Space, baseType.Local).Decl()
if err != nil {
cfg.logf("error generating MarshalXML method of %s: %v", s.name, err)
// add back the name field if we removed it in the previous step
if nameField != nil {
str.Fields.List = append([]*ast.Field{nameField}, str.Fields.List...)
}
return s
}

Expand Down
40 changes: 27 additions & 13 deletions xsdgen/example_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -78,8 +78,11 @@ func ExampleIgnoreAttributes() {
//
// package ws
//
// import "encoding/xml"
//
// type ArrayOfString struct {
// Items []string `xml:",any"`
// XMLName xml.Name `xml:"http://www.example.com/ ArrayOfString"`
// Items []string `xml:",any"`
// }
}

Expand Down Expand Up @@ -108,9 +111,12 @@ func ExampleIgnoreElements() {
//
// package ws
//
// import "encoding/xml"
//
// type Person struct {
// Name string `xml:"http://www.example.com/ name"`
// Deceased bool `xml:"http://schemas.xmlsoap.org/soap/encoding/ deceased"`
// XMLName xml.Name `xml:"http://www.example.com/ Person"`
// Name string `xml:"name"`
// Deceased bool `xml:"http://schemas.xmlsoap.org/soap/encoding/ deceased"`
// }
}

Expand Down Expand Up @@ -159,7 +165,10 @@ func ExampleReplace() {
//
// package ws
//
// import "encoding/xml"
//
// type StringArray struct {
// XMLName xml.Name `xml:"http://www.example.com/ ArrayOfString"`
// Items []string `xml:",any"`
// ArrayType string `xml:"arrayType,attr,omitempty"`
// }
Expand Down Expand Up @@ -188,11 +197,14 @@ func ExampleHandleSOAPArrayType() {
//
// package ws
//
// import "encoding/xml"
//
// type BoolArray struct {
// Items []bool `xml:",any"`
// Offset string `xml:"offset,attr,omitempty"`
// Id string `xml:"id,attr,omitempty"`
// Href string `xml:"href,attr,omitempty"`
// XMLName xml.Name `xml:"http://www.example.com/ BoolArray"`
// Items []bool `xml:",any"`
// Offset string `xml:"offset,attr,omitempty"`
// Id string `xml:"id,attr,omitempty"`
// Href string `xml:"href,attr,omitempty"`
// }
}

Expand Down Expand Up @@ -291,16 +303,17 @@ 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"`
// XMLName xml.Name `xml:"http://www.example.com/ book"`
// 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"`
// Published *xsdDate `xml:"published"`
// }
// layout.T = (*T)(t)
// layout.Published = (*xsdDate)(&layout.T.Published)
Expand All @@ -310,15 +323,16 @@ func ExampleUseFieldNames() {
// type T Book
// var overlay struct {
// *T
// Published *xsdDate `xml:"http://www.example.com/ published"`
// 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"`
// XMLName xml.Name `xml:"http://www.example.com/ library"`
// Book []Book `xml:"book"`
// }
//
// type xsdDate time.Time
Expand Down
24 changes: 23 additions & 1 deletion xsdgen/xsdgen.go
Original file line number Diff line number Diff line change
Expand Up @@ -684,7 +684,13 @@ 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)
var tag string
if t.Name.Space == el.Name.Space {
// No need to repeat the namespace if the parent already has it set
tag = fmt.Sprintf(`xml:"%s%s"`, el.Name.Local, options)
} else {
tag = fmt.Sprintf(`xml:"%s %s%s"`, el.Name.Space, 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)
Expand Down Expand Up @@ -771,6 +777,22 @@ func (cfg *Config) genComplexType(t *xsd.ComplexType) ([]spec, error) {
}
}
expr := gen.Struct(fields...)

// add XMLName field to struct that will be used by xml.Marshal for setting the element name
var tag string
if t.Name.Space != "" {
tag = fmt.Sprintf(`xml:"%s %s"`, t.Name.Space, t.Name.Local)
} else {
tag = fmt.Sprintf(`xml:"%s"`, t.Name.Local)
}
xmlNameField := &ast.Field{
Tag: gen.String(tag),
Names: []*ast.Ident{{Name: "XMLName"}},
Type: &ast.Ident{Name: "xml.Name"},
}

expr.Fields.List = append([]*ast.Field{xmlNameField}, expr.Fields.List...)

s := spec{
doc: t.Doc,
name: cfg.public(t.Name),
Expand Down