1 package xml
2
3 import (
4 "encoding/xml"
5 "fmt"
6 "strings"
7 )
8
9
10
11
12 type NodeDecoder struct {
13 Decoder *xml.Decoder
14 StartEl xml.StartElement
15 }
16
17
18 func WrapNodeDecoder(decoder *xml.Decoder, startEl xml.StartElement) NodeDecoder {
19 return NodeDecoder{
20 Decoder: decoder,
21 StartEl: startEl,
22 }
23 }
24
25
26
27
28 func (d NodeDecoder) Token() (t xml.StartElement, done bool, err error) {
29 for {
30 token, e := d.Decoder.Token()
31 if e != nil {
32 return t, done, e
33 }
34
35
36 if el, ok := token.(xml.EndElement); ok {
37 return t, el == d.StartEl.End(), err
38 }
39
40 if t, ok := token.(xml.StartElement); ok {
41 return restoreAttrNamespaces(t), false, err
42 }
43
44
45
46 }
47 }
48
49
50
51 func restoreAttrNamespaces(node xml.StartElement) xml.StartElement {
52 if len(node.Attr) == 0 {
53 return node
54 }
55
56
57 ns := map[string]string{}
58 for _, a := range node.Attr {
59 if a.Name.Space == "xmlns" {
60 ns[a.Value] = a.Name.Local
61 break
62 }
63 }
64
65 for i, a := range node.Attr {
66 if a.Name.Space == "xmlns" {
67 continue
68 }
69
70
71
72 if v, ok := ns[node.Attr[i].Name.Space]; ok {
73 node.Attr[i].Name.Space = v
74 }
75 }
76 return node
77 }
78
79
80
81
82 func (d NodeDecoder) GetElement(name string) (t xml.StartElement, err error) {
83 for {
84 token, done, err := d.Token()
85 if err != nil {
86 return t, err
87 }
88 if done {
89 return t, fmt.Errorf("%s node not found", name)
90 }
91 switch {
92 case strings.EqualFold(name, token.Name.Local):
93 return token, nil
94 default:
95 err = d.Decoder.Skip()
96 if err != nil {
97 return t, err
98 }
99 }
100 }
101 }
102
103
104
105
106 func (d NodeDecoder) Value() (c []byte, err error) {
107 t, e := d.Decoder.Token()
108 if e != nil {
109 return c, e
110 }
111
112 endElement := d.StartEl.End()
113
114 switch ev := t.(type) {
115 case xml.CharData:
116 c = ev.Copy()
117 case xml.EndElement:
118 if ev == endElement {
119 return []byte{}, err
120 }
121 return c, fmt.Errorf("expected value for %v element, got %T type %v instead", d.StartEl.Name.Local, t, t)
122 default:
123 return c, fmt.Errorf("expected value for %v element, got %T type %v instead", d.StartEl.Name.Local, t, t)
124 }
125
126 t, e = d.Decoder.Token()
127 if e != nil {
128 return c, e
129 }
130
131 if ev, ok := t.(xml.EndElement); ok {
132 if ev == endElement {
133 return c, err
134 }
135 }
136
137 return c, fmt.Errorf("expected end element %v, got %T type %v instead", endElement, t, t)
138 }
139
140
141
142
143 func FetchRootElement(decoder *xml.Decoder) (startElement xml.StartElement, err error) {
144 for {
145 t, e := decoder.Token()
146 if e != nil {
147 return startElement, e
148 }
149
150 if startElement, ok := t.(xml.StartElement); ok {
151 return startElement, err
152 }
153 }
154 }
155
View as plain text