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
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
@@ -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
}

@@ -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
}

@@ -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)
@@ -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
}

@@ -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
}

40 changes: 27 additions & 13 deletions xsdgen/example_test.go
Original file line number Diff line number Diff line change
@@ -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"`
// }
}

@@ -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"`
// }
}

@@ -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"`
// }
@@ -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"`
// }
}

@@ -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)
@@ -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
24 changes: 23 additions & 1 deletion xsdgen/xsdgen.go
Original file line number Diff line number Diff line change
@@ -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)
@@ -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),