9 // A XMLNode contains the values to be encoded or decoded.
11 Name xml.Name `json:",omitempty"`
12 Children map[string][]*XMLNode `json:",omitempty"`
13 Text string `json:",omitempty"`
14 Attr []xml.Attr `json:",omitempty"`
17 // NewXMLElement returns a pointer to a new XMLNode initialized to default values.
18 func NewXMLElement(name xml.Name) *XMLNode {
21 Children: map[string][]*XMLNode{},
26 // AddChild adds child to the XMLNode.
27 func (n *XMLNode) AddChild(child *XMLNode) {
28 if _, ok := n.Children[child.Name.Local]; !ok {
29 n.Children[child.Name.Local] = []*XMLNode{}
31 n.Children[child.Name.Local] = append(n.Children[child.Name.Local], child)
34 // XMLToStruct converts a xml.Decoder stream to XMLNode with nested values.
35 func XMLToStruct(d *xml.Decoder, s *xml.StartElement) (*XMLNode, error) {
39 if tok == nil || err == io.EOF {
46 switch typed := tok.(type) {
48 out.Text = string(typed.Copy())
49 case xml.StartElement:
52 if out.Children == nil {
53 out.Children = map[string][]*XMLNode{}
56 name := typed.Name.Local
57 slice := out.Children[name]
61 node, e := XMLToStruct(d, &el)
65 node.Name = typed.Name
66 slice = append(slice, node)
67 out.Children[name] = slice
69 if s != nil && s.Name.Local == typed.Name.Local { // matching end token
77 // StructToXML writes an XMLNode to a xml.Encoder as tokens.
78 func StructToXML(e *xml.Encoder, node *XMLNode, sorted bool) error {
79 e.EncodeToken(xml.StartElement{Name: node.Name, Attr: node.Attr})
82 e.EncodeToken(xml.CharData([]byte(node.Text)))
84 sortedNames := []string{}
85 for k := range node.Children {
86 sortedNames = append(sortedNames, k)
88 sort.Strings(sortedNames)
90 for _, k := range sortedNames {
91 for _, v := range node.Children[k] {
92 StructToXML(e, v, sorted)
96 for _, c := range node.Children {
98 StructToXML(e, v, sorted)
103 e.EncodeToken(xml.EndElement{Name: node.Name})