XMLToStruct converts a xml.Decoder stream to XMLNode with nested values.
(d *xml.Decoder, s *xml.StartElement, ignoreIndentation bool)
| 40 | |
| 41 | // XMLToStruct converts a xml.Decoder stream to XMLNode with nested values. |
| 42 | func XMLToStruct(d *xml.Decoder, s *xml.StartElement, ignoreIndentation bool) (*XMLNode, error) { |
| 43 | out := &XMLNode{} |
| 44 | |
| 45 | for { |
| 46 | tok, err := d.Token() |
| 47 | if err != nil { |
| 48 | if err == io.EOF { |
| 49 | break |
| 50 | } else { |
| 51 | return out, err |
| 52 | } |
| 53 | } |
| 54 | |
| 55 | if tok == nil { |
| 56 | break |
| 57 | } |
| 58 | |
| 59 | switch typed := tok.(type) { |
| 60 | case xml.CharData: |
| 61 | text := string(typed.Copy()) |
| 62 | if ignoreIndentation { |
| 63 | text = strings.TrimSpace(text) |
| 64 | } |
| 65 | if len(text) != 0 { |
| 66 | out.Text = text |
| 67 | } |
| 68 | case xml.StartElement: |
| 69 | el := typed.Copy() |
| 70 | out.Attr = el.Attr |
| 71 | if out.Children == nil { |
| 72 | out.Children = map[string][]*XMLNode{} |
| 73 | } |
| 74 | |
| 75 | name := typed.Name.Local |
| 76 | slice := out.Children[name] |
| 77 | if slice == nil { |
| 78 | slice = []*XMLNode{} |
| 79 | } |
| 80 | node, e := XMLToStruct(d, &el, ignoreIndentation) |
| 81 | out.findNamespaces() |
| 82 | if e != nil { |
| 83 | return out, e |
| 84 | } |
| 85 | |
| 86 | node.Name = typed.Name |
| 87 | node.findNamespaces() |
| 88 | |
| 89 | // Add attributes onto the node |
| 90 | node.Attr = el.Attr |
| 91 | |
| 92 | tempOut := *out |
| 93 | // Save into a temp variable, simply because out gets squashed during |
| 94 | // loop iterations |
| 95 | node.parent = &tempOut |
| 96 | slice = append(slice, node) |
| 97 | out.Children[name] = slice |
| 98 | case xml.EndElement: |
| 99 | if s != nil && s.Name.Local == typed.Name.Local { // matching end token |
no test coverage detected