aboutsummaryrefslogtreecommitdiffhomepage
path: root/vendor/github.com/aws/aws-sdk-go/private/protocol/xml/xmlutil/xml_to_struct.go
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com/aws/aws-sdk-go/private/protocol/xml/xmlutil/xml_to_struct.go')
-rw-r--r--vendor/github.com/aws/aws-sdk-go/private/protocol/xml/xmlutil/xml_to_struct.go147
1 files changed, 147 insertions, 0 deletions
diff --git a/vendor/github.com/aws/aws-sdk-go/private/protocol/xml/xmlutil/xml_to_struct.go b/vendor/github.com/aws/aws-sdk-go/private/protocol/xml/xmlutil/xml_to_struct.go
new file mode 100644
index 0000000..3e970b6
--- /dev/null
+++ b/vendor/github.com/aws/aws-sdk-go/private/protocol/xml/xmlutil/xml_to_struct.go
@@ -0,0 +1,147 @@
1package xmlutil
2
3import (
4 "encoding/xml"
5 "fmt"
6 "io"
7 "sort"
8)
9
10// A XMLNode contains the values to be encoded or decoded.
11type XMLNode struct {
12 Name xml.Name `json:",omitempty"`
13 Children map[string][]*XMLNode `json:",omitempty"`
14 Text string `json:",omitempty"`
15 Attr []xml.Attr `json:",omitempty"`
16
17 namespaces map[string]string
18 parent *XMLNode
19}
20
21// NewXMLElement returns a pointer to a new XMLNode initialized to default values.
22func NewXMLElement(name xml.Name) *XMLNode {
23 return &XMLNode{
24 Name: name,
25 Children: map[string][]*XMLNode{},
26 Attr: []xml.Attr{},
27 }
28}
29
30// AddChild adds child to the XMLNode.
31func (n *XMLNode) AddChild(child *XMLNode) {
32 if _, ok := n.Children[child.Name.Local]; !ok {
33 n.Children[child.Name.Local] = []*XMLNode{}
34 }
35 n.Children[child.Name.Local] = append(n.Children[child.Name.Local], child)
36}
37
38// XMLToStruct converts a xml.Decoder stream to XMLNode with nested values.
39func XMLToStruct(d *xml.Decoder, s *xml.StartElement) (*XMLNode, error) {
40 out := &XMLNode{}
41 for {
42 tok, err := d.Token()
43 if err != nil {
44 if err == io.EOF {
45 break
46 } else {
47 return out, err
48 }
49 }
50
51 if tok == nil {
52 break
53 }
54
55 switch typed := tok.(type) {
56 case xml.CharData:
57 out.Text = string(typed.Copy())
58 case xml.StartElement:
59 el := typed.Copy()
60 out.Attr = el.Attr
61 if out.Children == nil {
62 out.Children = map[string][]*XMLNode{}
63 }
64
65 name := typed.Name.Local
66 slice := out.Children[name]
67 if slice == nil {
68 slice = []*XMLNode{}
69 }
70 node, e := XMLToStruct(d, &el)
71 out.findNamespaces()
72 if e != nil {
73 return out, e
74 }
75 node.Name = typed.Name
76 node.findNamespaces()
77 tempOut := *out
78 // Save into a temp variable, simply because out gets squashed during
79 // loop iterations
80 node.parent = &tempOut
81 slice = append(slice, node)
82 out.Children[name] = slice
83 case xml.EndElement:
84 if s != nil && s.Name.Local == typed.Name.Local { // matching end token
85 return out, nil
86 }
87 out = &XMLNode{}
88 }
89 }
90 return out, nil
91}
92
93func (n *XMLNode) findNamespaces() {
94 ns := map[string]string{}
95 for _, a := range n.Attr {
96 if a.Name.Space == "xmlns" {
97 ns[a.Value] = a.Name.Local
98 }
99 }
100
101 n.namespaces = ns
102}
103
104func (n *XMLNode) findElem(name string) (string, bool) {
105 for node := n; node != nil; node = node.parent {
106 for _, a := range node.Attr {
107 namespace := a.Name.Space
108 if v, ok := node.namespaces[namespace]; ok {
109 namespace = v
110 }
111 if name == fmt.Sprintf("%s:%s", namespace, a.Name.Local) {
112 return a.Value, true
113 }
114 }
115 }
116 return "", false
117}
118
119// StructToXML writes an XMLNode to a xml.Encoder as tokens.
120func StructToXML(e *xml.Encoder, node *XMLNode, sorted bool) error {
121 e.EncodeToken(xml.StartElement{Name: node.Name, Attr: node.Attr})
122
123 if node.Text != "" {
124 e.EncodeToken(xml.CharData([]byte(node.Text)))
125 } else if sorted {
126 sortedNames := []string{}
127 for k := range node.Children {
128 sortedNames = append(sortedNames, k)
129 }
130 sort.Strings(sortedNames)
131
132 for _, k := range sortedNames {
133 for _, v := range node.Children[k] {
134 StructToXML(e, v, sorted)
135 }
136 }
137 } else {
138 for _, c := range node.Children {
139 for _, v := range c {
140 StructToXML(e, v, sorted)
141 }
142 }
143 }
144
145 e.EncodeToken(xml.EndElement{Name: node.Name})
146 return e.Flush()
147}