Use a vendor directory for repeatable builds - fixes #816
This is using godep to manage the vendor directory.
This commit is contained in:
parent
01be5bff02
commit
f7af730b50
637 changed files with 247384 additions and 11 deletions
293
vendor/github.com/aws/aws-sdk-go/private/protocol/xml/xmlutil/build.go
generated
vendored
Normal file
293
vendor/github.com/aws/aws-sdk-go/private/protocol/xml/xmlutil/build.go
generated
vendored
Normal file
|
@ -0,0 +1,293 @@
|
|||
// Package xmlutil provides XML serialization of AWS requests and responses.
|
||||
package xmlutil
|
||||
|
||||
import (
|
||||
"encoding/base64"
|
||||
"encoding/xml"
|
||||
"fmt"
|
||||
"reflect"
|
||||
"sort"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/aws/aws-sdk-go/private/protocol"
|
||||
)
|
||||
|
||||
// BuildXML will serialize params into an xml.Encoder.
|
||||
// Error will be returned if the serialization of any of the params or nested values fails.
|
||||
func BuildXML(params interface{}, e *xml.Encoder) error {
|
||||
b := xmlBuilder{encoder: e, namespaces: map[string]string{}}
|
||||
root := NewXMLElement(xml.Name{})
|
||||
if err := b.buildValue(reflect.ValueOf(params), root, ""); err != nil {
|
||||
return err
|
||||
}
|
||||
for _, c := range root.Children {
|
||||
for _, v := range c {
|
||||
return StructToXML(e, v, false)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Returns the reflection element of a value, if it is a pointer.
|
||||
func elemOf(value reflect.Value) reflect.Value {
|
||||
for value.Kind() == reflect.Ptr {
|
||||
value = value.Elem()
|
||||
}
|
||||
return value
|
||||
}
|
||||
|
||||
// A xmlBuilder serializes values from Go code to XML
|
||||
type xmlBuilder struct {
|
||||
encoder *xml.Encoder
|
||||
namespaces map[string]string
|
||||
}
|
||||
|
||||
// buildValue generic XMLNode builder for any type. Will build value for their specific type
|
||||
// struct, list, map, scalar.
|
||||
//
|
||||
// Also takes a "type" tag value to set what type a value should be converted to XMLNode as. If
|
||||
// type is not provided reflect will be used to determine the value's type.
|
||||
func (b *xmlBuilder) buildValue(value reflect.Value, current *XMLNode, tag reflect.StructTag) error {
|
||||
value = elemOf(value)
|
||||
if !value.IsValid() { // no need to handle zero values
|
||||
return nil
|
||||
} else if tag.Get("location") != "" { // don't handle non-body location values
|
||||
return nil
|
||||
}
|
||||
|
||||
t := tag.Get("type")
|
||||
if t == "" {
|
||||
switch value.Kind() {
|
||||
case reflect.Struct:
|
||||
t = "structure"
|
||||
case reflect.Slice:
|
||||
t = "list"
|
||||
case reflect.Map:
|
||||
t = "map"
|
||||
}
|
||||
}
|
||||
|
||||
switch t {
|
||||
case "structure":
|
||||
if field, ok := value.Type().FieldByName("_"); ok {
|
||||
tag = tag + reflect.StructTag(" ") + field.Tag
|
||||
}
|
||||
return b.buildStruct(value, current, tag)
|
||||
case "list":
|
||||
return b.buildList(value, current, tag)
|
||||
case "map":
|
||||
return b.buildMap(value, current, tag)
|
||||
default:
|
||||
return b.buildScalar(value, current, tag)
|
||||
}
|
||||
}
|
||||
|
||||
// buildStruct adds a struct and its fields to the current XMLNode. All fields any any nested
|
||||
// types are converted to XMLNodes also.
|
||||
func (b *xmlBuilder) buildStruct(value reflect.Value, current *XMLNode, tag reflect.StructTag) error {
|
||||
if !value.IsValid() {
|
||||
return nil
|
||||
}
|
||||
|
||||
fieldAdded := false
|
||||
|
||||
// unwrap payloads
|
||||
if payload := tag.Get("payload"); payload != "" {
|
||||
field, _ := value.Type().FieldByName(payload)
|
||||
tag = field.Tag
|
||||
value = elemOf(value.FieldByName(payload))
|
||||
|
||||
if !value.IsValid() {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
child := NewXMLElement(xml.Name{Local: tag.Get("locationName")})
|
||||
|
||||
// there is an xmlNamespace associated with this struct
|
||||
if prefix, uri := tag.Get("xmlPrefix"), tag.Get("xmlURI"); uri != "" {
|
||||
ns := xml.Attr{
|
||||
Name: xml.Name{Local: "xmlns"},
|
||||
Value: uri,
|
||||
}
|
||||
if prefix != "" {
|
||||
b.namespaces[prefix] = uri // register the namespace
|
||||
ns.Name.Local = "xmlns:" + prefix
|
||||
}
|
||||
|
||||
child.Attr = append(child.Attr, ns)
|
||||
}
|
||||
|
||||
t := value.Type()
|
||||
for i := 0; i < value.NumField(); i++ {
|
||||
member := elemOf(value.Field(i))
|
||||
field := t.Field(i)
|
||||
|
||||
if field.PkgPath != "" {
|
||||
continue // ignore unexported fields
|
||||
}
|
||||
|
||||
mTag := field.Tag
|
||||
if mTag.Get("location") != "" { // skip non-body members
|
||||
continue
|
||||
}
|
||||
|
||||
if protocol.CanSetIdempotencyToken(value.Field(i), field) {
|
||||
token := protocol.GetIdempotencyToken()
|
||||
member = reflect.ValueOf(token)
|
||||
}
|
||||
|
||||
memberName := mTag.Get("locationName")
|
||||
if memberName == "" {
|
||||
memberName = field.Name
|
||||
mTag = reflect.StructTag(string(mTag) + ` locationName:"` + memberName + `"`)
|
||||
}
|
||||
if err := b.buildValue(member, child, mTag); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
fieldAdded = true
|
||||
}
|
||||
|
||||
if fieldAdded { // only append this child if we have one ore more valid members
|
||||
current.AddChild(child)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// buildList adds the value's list items to the current XMLNode as children nodes. All
|
||||
// nested values in the list are converted to XMLNodes also.
|
||||
func (b *xmlBuilder) buildList(value reflect.Value, current *XMLNode, tag reflect.StructTag) error {
|
||||
if value.IsNil() { // don't build omitted lists
|
||||
return nil
|
||||
}
|
||||
|
||||
// check for unflattened list member
|
||||
flattened := tag.Get("flattened") != ""
|
||||
|
||||
xname := xml.Name{Local: tag.Get("locationName")}
|
||||
if flattened {
|
||||
for i := 0; i < value.Len(); i++ {
|
||||
child := NewXMLElement(xname)
|
||||
current.AddChild(child)
|
||||
if err := b.buildValue(value.Index(i), child, ""); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
} else {
|
||||
list := NewXMLElement(xname)
|
||||
current.AddChild(list)
|
||||
|
||||
for i := 0; i < value.Len(); i++ {
|
||||
iname := tag.Get("locationNameList")
|
||||
if iname == "" {
|
||||
iname = "member"
|
||||
}
|
||||
|
||||
child := NewXMLElement(xml.Name{Local: iname})
|
||||
list.AddChild(child)
|
||||
if err := b.buildValue(value.Index(i), child, ""); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// buildMap adds the value's key/value pairs to the current XMLNode as children nodes. All
|
||||
// nested values in the map are converted to XMLNodes also.
|
||||
//
|
||||
// Error will be returned if it is unable to build the map's values into XMLNodes
|
||||
func (b *xmlBuilder) buildMap(value reflect.Value, current *XMLNode, tag reflect.StructTag) error {
|
||||
if value.IsNil() { // don't build omitted maps
|
||||
return nil
|
||||
}
|
||||
|
||||
maproot := NewXMLElement(xml.Name{Local: tag.Get("locationName")})
|
||||
current.AddChild(maproot)
|
||||
current = maproot
|
||||
|
||||
kname, vname := "key", "value"
|
||||
if n := tag.Get("locationNameKey"); n != "" {
|
||||
kname = n
|
||||
}
|
||||
if n := tag.Get("locationNameValue"); n != "" {
|
||||
vname = n
|
||||
}
|
||||
|
||||
// sorting is not required for compliance, but it makes testing easier
|
||||
keys := make([]string, value.Len())
|
||||
for i, k := range value.MapKeys() {
|
||||
keys[i] = k.String()
|
||||
}
|
||||
sort.Strings(keys)
|
||||
|
||||
for _, k := range keys {
|
||||
v := value.MapIndex(reflect.ValueOf(k))
|
||||
|
||||
mapcur := current
|
||||
if tag.Get("flattened") == "" { // add "entry" tag to non-flat maps
|
||||
child := NewXMLElement(xml.Name{Local: "entry"})
|
||||
mapcur.AddChild(child)
|
||||
mapcur = child
|
||||
}
|
||||
|
||||
kchild := NewXMLElement(xml.Name{Local: kname})
|
||||
kchild.Text = k
|
||||
vchild := NewXMLElement(xml.Name{Local: vname})
|
||||
mapcur.AddChild(kchild)
|
||||
mapcur.AddChild(vchild)
|
||||
|
||||
if err := b.buildValue(v, vchild, ""); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// buildScalar will convert the value into a string and append it as a attribute or child
|
||||
// of the current XMLNode.
|
||||
//
|
||||
// The value will be added as an attribute if tag contains a "xmlAttribute" attribute value.
|
||||
//
|
||||
// Error will be returned if the value type is unsupported.
|
||||
func (b *xmlBuilder) buildScalar(value reflect.Value, current *XMLNode, tag reflect.StructTag) error {
|
||||
var str string
|
||||
switch converted := value.Interface().(type) {
|
||||
case string:
|
||||
str = converted
|
||||
case []byte:
|
||||
if !value.IsNil() {
|
||||
str = base64.StdEncoding.EncodeToString(converted)
|
||||
}
|
||||
case bool:
|
||||
str = strconv.FormatBool(converted)
|
||||
case int64:
|
||||
str = strconv.FormatInt(converted, 10)
|
||||
case int:
|
||||
str = strconv.Itoa(converted)
|
||||
case float64:
|
||||
str = strconv.FormatFloat(converted, 'f', -1, 64)
|
||||
case float32:
|
||||
str = strconv.FormatFloat(float64(converted), 'f', -1, 32)
|
||||
case time.Time:
|
||||
const ISO8601UTC = "2006-01-02T15:04:05Z"
|
||||
str = converted.UTC().Format(ISO8601UTC)
|
||||
default:
|
||||
return fmt.Errorf("unsupported value for param %s: %v (%s)",
|
||||
tag.Get("locationName"), value.Interface(), value.Type().Name())
|
||||
}
|
||||
|
||||
xname := xml.Name{Local: tag.Get("locationName")}
|
||||
if tag.Get("xmlAttribute") != "" { // put into current node's attribute list
|
||||
attr := xml.Attr{Name: xname, Value: str}
|
||||
current.Attr = append(current.Attr, attr)
|
||||
} else { // regular text node
|
||||
current.AddChild(&XMLNode{Name: xname, Text: str})
|
||||
}
|
||||
return nil
|
||||
}
|
260
vendor/github.com/aws/aws-sdk-go/private/protocol/xml/xmlutil/unmarshal.go
generated
vendored
Normal file
260
vendor/github.com/aws/aws-sdk-go/private/protocol/xml/xmlutil/unmarshal.go
generated
vendored
Normal file
|
@ -0,0 +1,260 @@
|
|||
package xmlutil
|
||||
|
||||
import (
|
||||
"encoding/base64"
|
||||
"encoding/xml"
|
||||
"fmt"
|
||||
"io"
|
||||
"reflect"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
// UnmarshalXML deserializes an xml.Decoder into the container v. V
|
||||
// needs to match the shape of the XML expected to be decoded.
|
||||
// If the shape doesn't match unmarshaling will fail.
|
||||
func UnmarshalXML(v interface{}, d *xml.Decoder, wrapper string) error {
|
||||
n, _ := XMLToStruct(d, nil)
|
||||
if n.Children != nil {
|
||||
for _, root := range n.Children {
|
||||
for _, c := range root {
|
||||
if wrappedChild, ok := c.Children[wrapper]; ok {
|
||||
c = wrappedChild[0] // pull out wrapped element
|
||||
}
|
||||
|
||||
err := parse(reflect.ValueOf(v), c, "")
|
||||
if err != nil {
|
||||
if err == io.EOF {
|
||||
return nil
|
||||
}
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// parse deserializes any value from the XMLNode. The type tag is used to infer the type, or reflect
|
||||
// will be used to determine the type from r.
|
||||
func parse(r reflect.Value, node *XMLNode, tag reflect.StructTag) error {
|
||||
rtype := r.Type()
|
||||
if rtype.Kind() == reflect.Ptr {
|
||||
rtype = rtype.Elem() // check kind of actual element type
|
||||
}
|
||||
|
||||
t := tag.Get("type")
|
||||
if t == "" {
|
||||
switch rtype.Kind() {
|
||||
case reflect.Struct:
|
||||
t = "structure"
|
||||
case reflect.Slice:
|
||||
t = "list"
|
||||
case reflect.Map:
|
||||
t = "map"
|
||||
}
|
||||
}
|
||||
|
||||
switch t {
|
||||
case "structure":
|
||||
if field, ok := rtype.FieldByName("_"); ok {
|
||||
tag = field.Tag
|
||||
}
|
||||
return parseStruct(r, node, tag)
|
||||
case "list":
|
||||
return parseList(r, node, tag)
|
||||
case "map":
|
||||
return parseMap(r, node, tag)
|
||||
default:
|
||||
return parseScalar(r, node, tag)
|
||||
}
|
||||
}
|
||||
|
||||
// parseStruct deserializes a structure and its fields from an XMLNode. Any nested
|
||||
// types in the structure will also be deserialized.
|
||||
func parseStruct(r reflect.Value, node *XMLNode, tag reflect.StructTag) error {
|
||||
t := r.Type()
|
||||
if r.Kind() == reflect.Ptr {
|
||||
if r.IsNil() { // create the structure if it's nil
|
||||
s := reflect.New(r.Type().Elem())
|
||||
r.Set(s)
|
||||
r = s
|
||||
}
|
||||
|
||||
r = r.Elem()
|
||||
t = t.Elem()
|
||||
}
|
||||
|
||||
// unwrap any payloads
|
||||
if payload := tag.Get("payload"); payload != "" {
|
||||
field, _ := t.FieldByName(payload)
|
||||
return parseStruct(r.FieldByName(payload), node, field.Tag)
|
||||
}
|
||||
|
||||
for i := 0; i < t.NumField(); i++ {
|
||||
field := t.Field(i)
|
||||
if c := field.Name[0:1]; strings.ToLower(c) == c {
|
||||
continue // ignore unexported fields
|
||||
}
|
||||
|
||||
// figure out what this field is called
|
||||
name := field.Name
|
||||
if field.Tag.Get("flattened") != "" && field.Tag.Get("locationNameList") != "" {
|
||||
name = field.Tag.Get("locationNameList")
|
||||
} else if locName := field.Tag.Get("locationName"); locName != "" {
|
||||
name = locName
|
||||
}
|
||||
|
||||
// try to find the field by name in elements
|
||||
elems := node.Children[name]
|
||||
|
||||
if elems == nil { // try to find the field in attributes
|
||||
for _, a := range node.Attr {
|
||||
if name == a.Name.Local {
|
||||
// turn this into a text node for de-serializing
|
||||
elems = []*XMLNode{{Text: a.Value}}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
member := r.FieldByName(field.Name)
|
||||
for _, elem := range elems {
|
||||
err := parse(member, elem, field.Tag)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// parseList deserializes a list of values from an XML node. Each list entry
|
||||
// will also be deserialized.
|
||||
func parseList(r reflect.Value, node *XMLNode, tag reflect.StructTag) error {
|
||||
t := r.Type()
|
||||
|
||||
if tag.Get("flattened") == "" { // look at all item entries
|
||||
mname := "member"
|
||||
if name := tag.Get("locationNameList"); name != "" {
|
||||
mname = name
|
||||
}
|
||||
|
||||
if Children, ok := node.Children[mname]; ok {
|
||||
if r.IsNil() {
|
||||
r.Set(reflect.MakeSlice(t, len(Children), len(Children)))
|
||||
}
|
||||
|
||||
for i, c := range Children {
|
||||
err := parse(r.Index(i), c, "")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
} else { // flattened list means this is a single element
|
||||
if r.IsNil() {
|
||||
r.Set(reflect.MakeSlice(t, 0, 0))
|
||||
}
|
||||
|
||||
childR := reflect.Zero(t.Elem())
|
||||
r.Set(reflect.Append(r, childR))
|
||||
err := parse(r.Index(r.Len()-1), node, "")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// parseMap deserializes a map from an XMLNode. The direct children of the XMLNode
|
||||
// will also be deserialized as map entries.
|
||||
func parseMap(r reflect.Value, node *XMLNode, tag reflect.StructTag) error {
|
||||
if r.IsNil() {
|
||||
r.Set(reflect.MakeMap(r.Type()))
|
||||
}
|
||||
|
||||
if tag.Get("flattened") == "" { // look at all child entries
|
||||
for _, entry := range node.Children["entry"] {
|
||||
parseMapEntry(r, entry, tag)
|
||||
}
|
||||
} else { // this element is itself an entry
|
||||
parseMapEntry(r, node, tag)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// parseMapEntry deserializes a map entry from a XML node.
|
||||
func parseMapEntry(r reflect.Value, node *XMLNode, tag reflect.StructTag) error {
|
||||
kname, vname := "key", "value"
|
||||
if n := tag.Get("locationNameKey"); n != "" {
|
||||
kname = n
|
||||
}
|
||||
if n := tag.Get("locationNameValue"); n != "" {
|
||||
vname = n
|
||||
}
|
||||
|
||||
keys, ok := node.Children[kname]
|
||||
values := node.Children[vname]
|
||||
if ok {
|
||||
for i, key := range keys {
|
||||
keyR := reflect.ValueOf(key.Text)
|
||||
value := values[i]
|
||||
valueR := reflect.New(r.Type().Elem()).Elem()
|
||||
|
||||
parse(valueR, value, "")
|
||||
r.SetMapIndex(keyR, valueR)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// parseScaller deserializes an XMLNode value into a concrete type based on the
|
||||
// interface type of r.
|
||||
//
|
||||
// Error is returned if the deserialization fails due to invalid type conversion,
|
||||
// or unsupported interface type.
|
||||
func parseScalar(r reflect.Value, node *XMLNode, tag reflect.StructTag) error {
|
||||
switch r.Interface().(type) {
|
||||
case *string:
|
||||
r.Set(reflect.ValueOf(&node.Text))
|
||||
return nil
|
||||
case []byte:
|
||||
b, err := base64.StdEncoding.DecodeString(node.Text)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
r.Set(reflect.ValueOf(b))
|
||||
case *bool:
|
||||
v, err := strconv.ParseBool(node.Text)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
r.Set(reflect.ValueOf(&v))
|
||||
case *int64:
|
||||
v, err := strconv.ParseInt(node.Text, 10, 64)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
r.Set(reflect.ValueOf(&v))
|
||||
case *float64:
|
||||
v, err := strconv.ParseFloat(node.Text, 64)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
r.Set(reflect.ValueOf(&v))
|
||||
case *time.Time:
|
||||
const ISO8601UTC = "2006-01-02T15:04:05Z"
|
||||
t, err := time.Parse(ISO8601UTC, node.Text)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
r.Set(reflect.ValueOf(&t))
|
||||
default:
|
||||
return fmt.Errorf("unsupported value: %v (%s)", r.Interface(), r.Type())
|
||||
}
|
||||
return nil
|
||||
}
|
105
vendor/github.com/aws/aws-sdk-go/private/protocol/xml/xmlutil/xml_to_struct.go
generated
vendored
Normal file
105
vendor/github.com/aws/aws-sdk-go/private/protocol/xml/xmlutil/xml_to_struct.go
generated
vendored
Normal file
|
@ -0,0 +1,105 @@
|
|||
package xmlutil
|
||||
|
||||
import (
|
||||
"encoding/xml"
|
||||
"io"
|
||||
"sort"
|
||||
)
|
||||
|
||||
// A XMLNode contains the values to be encoded or decoded.
|
||||
type XMLNode struct {
|
||||
Name xml.Name `json:",omitempty"`
|
||||
Children map[string][]*XMLNode `json:",omitempty"`
|
||||
Text string `json:",omitempty"`
|
||||
Attr []xml.Attr `json:",omitempty"`
|
||||
}
|
||||
|
||||
// NewXMLElement returns a pointer to a new XMLNode initialized to default values.
|
||||
func NewXMLElement(name xml.Name) *XMLNode {
|
||||
return &XMLNode{
|
||||
Name: name,
|
||||
Children: map[string][]*XMLNode{},
|
||||
Attr: []xml.Attr{},
|
||||
}
|
||||
}
|
||||
|
||||
// AddChild adds child to the XMLNode.
|
||||
func (n *XMLNode) AddChild(child *XMLNode) {
|
||||
if _, ok := n.Children[child.Name.Local]; !ok {
|
||||
n.Children[child.Name.Local] = []*XMLNode{}
|
||||
}
|
||||
n.Children[child.Name.Local] = append(n.Children[child.Name.Local], child)
|
||||
}
|
||||
|
||||
// XMLToStruct converts a xml.Decoder stream to XMLNode with nested values.
|
||||
func XMLToStruct(d *xml.Decoder, s *xml.StartElement) (*XMLNode, error) {
|
||||
out := &XMLNode{}
|
||||
for {
|
||||
tok, err := d.Token()
|
||||
if tok == nil || err == io.EOF {
|
||||
break
|
||||
}
|
||||
if err != nil {
|
||||
return out, err
|
||||
}
|
||||
|
||||
switch typed := tok.(type) {
|
||||
case xml.CharData:
|
||||
out.Text = string(typed.Copy())
|
||||
case xml.StartElement:
|
||||
el := typed.Copy()
|
||||
out.Attr = el.Attr
|
||||
if out.Children == nil {
|
||||
out.Children = map[string][]*XMLNode{}
|
||||
}
|
||||
|
||||
name := typed.Name.Local
|
||||
slice := out.Children[name]
|
||||
if slice == nil {
|
||||
slice = []*XMLNode{}
|
||||
}
|
||||
node, e := XMLToStruct(d, &el)
|
||||
if e != nil {
|
||||
return out, e
|
||||
}
|
||||
node.Name = typed.Name
|
||||
slice = append(slice, node)
|
||||
out.Children[name] = slice
|
||||
case xml.EndElement:
|
||||
if s != nil && s.Name.Local == typed.Name.Local { // matching end token
|
||||
return out, nil
|
||||
}
|
||||
}
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
// StructToXML writes an XMLNode to a xml.Encoder as tokens.
|
||||
func StructToXML(e *xml.Encoder, node *XMLNode, sorted bool) error {
|
||||
e.EncodeToken(xml.StartElement{Name: node.Name, Attr: node.Attr})
|
||||
|
||||
if node.Text != "" {
|
||||
e.EncodeToken(xml.CharData([]byte(node.Text)))
|
||||
} else if sorted {
|
||||
sortedNames := []string{}
|
||||
for k := range node.Children {
|
||||
sortedNames = append(sortedNames, k)
|
||||
}
|
||||
sort.Strings(sortedNames)
|
||||
|
||||
for _, k := range sortedNames {
|
||||
for _, v := range node.Children[k] {
|
||||
StructToXML(e, v, sorted)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for _, c := range node.Children {
|
||||
for _, v := range c {
|
||||
StructToXML(e, v, sorted)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
e.EncodeToken(xml.EndElement{Name: node.Name})
|
||||
return e.Flush()
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue