package xmlutil

import (
	
	
	
	
)
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"`

	namespaces map[string]string
	parent     *XMLNode
}
NewXMLElement returns a pointer to a new XMLNode initialized to default values.
func ( xml.Name) *XMLNode {
	return &XMLNode{
		Name:     ,
		Children: map[string][]*XMLNode{},
		Attr:     []xml.Attr{},
	}
}
AddChild adds child to the XMLNode.
func ( *XMLNode) ( *XMLNode) {
	.parent = 
	if ,  := .Children[.Name.Local]; ! {
		.Children[.Name.Local] = []*XMLNode{}
	}
	.Children[.Name.Local] = append(.Children[.Name.Local], )
}
XMLToStruct converts a xml.Decoder stream to XMLNode with nested values.
func ( *xml.Decoder,  *xml.StartElement) (*XMLNode, error) {
	 := &XMLNode{}
	for {
		,  := .Token()
		if  != nil {
			if  == io.EOF {
				break
			} else {
				return , 
			}
		}

		if  == nil {
			break
		}

		switch typed := .(type) {
		case xml.CharData:
			.Text = string(.Copy())
		case xml.StartElement:
			 := .Copy()
			.Attr = .Attr
			if .Children == nil {
				.Children = map[string][]*XMLNode{}
			}

			 := .Name.Local
			 := .Children[]
			if  == nil {
				 = []*XMLNode{}
			}
			,  := (, &)
			.findNamespaces()
			if  != nil {
				return , 
			}
			.Name = .Name
			.findNamespaces()
Save into a temp variable, simply because out gets squashed during loop iterations
			.parent = &
			 = append(, )
			.Children[] = 
		case xml.EndElement:
			if  != nil && .Name.Local == .Name.Local { // matching end token
				return , nil
			}
			 = &XMLNode{}
		}
	}
	return , nil
}

func ( *XMLNode) () {
	 := map[string]string{}
	for ,  := range .Attr {
		if .Name.Space == "xmlns" {
			[.Value] = .Name.Local
		}
	}

	.namespaces = 
}

func ( *XMLNode) ( string) (string, bool) {
	for  := ;  != nil;  = .parent {
		for ,  := range .Attr {
			 := .Name.Space
			if ,  := .namespaces[];  {
				 = 
			}
			if  == fmt.Sprintf("%s:%s", , .Name.Local) {
				return .Value, true
			}
		}
	}
	return "", false
}
StructToXML writes an XMLNode to a xml.Encoder as tokens.
Sort Attributes
	 := .Attr
	if  {
		 := make([]xml.Attr, len())
		for ,  := range .Attr {
			 = append(, )
		}
		sort.Sort(xmlAttrSlice())
		 = 
	}

	.EncodeToken(xml.StartElement{Name: .Name, Attr: })

	if .Text != "" {
		.EncodeToken(xml.CharData([]byte(.Text)))
	} else if  {
		 := []string{}
		for  := range .Children {
			 = append(, )
		}
		sort.Strings()

		for ,  := range  {
			for ,  := range .Children[] {
				(, , )
			}
		}
	} else {
		for ,  := range .Children {
			for ,  := range  {
				(, , )
			}
		}
	}

	.EncodeToken(xml.EndElement{Name: .Name})
	return .Flush()