func HandleXmlReader(xmlReader io.Reader, mapHandler func(Map) bool, errHandler func(error) bool) error {
	var n int
	for {
		m, merr := NewMapXmlReader(xmlReader)
		n++
		if merr != nil && merr != io.EOF {
			merr = fmt.Errorf("[xmlReader: %d] %s", n, merr.Error())
			if ok := errHandler(merr); !ok {
				return merr
			}
			continue
		}
		if len(m) != 0 {
			if ok := mapHandler(m); !ok {
				break
			}
		} else if merr != io.EOF {
			time.Sleep(xhandlerPollInterval)
		}
		if merr == io.EOF {
			break
		}
	}
	return nil
}
Bulk process XML using handlers that process a Map value.
'rdr' is an io.Reader for XML (stream)
'mapHandler' is the Map processor. Return of 'false' stops io.Reader processing.
'errHandler' is the error processor. Return of 'false' stops io.Reader processing and returns the error.
Note: mapHandler() and errHandler() calls are blocking, so reading and processing of messages is serialized.
This means that you can stop reading the file on error or after processing a particular message.
To have reading and handling run concurrently, pass argument to a go routine in handler and return 'true'.
package mxj
import (
	"bytes"
	"encoding/json"
	"encoding/xml"
	"errors"
	"fmt"
	"io"
	"reflect"
	"sort"
	"strconv"
	"strings"
	"time"
)
var XmlCharsetReader func(charset string, input io.Reader) (io.Reader, error)
func NewMapXml(xmlVal []byte, cast ...bool) (Map, error) {
	var r bool
	if len(cast) == 1 {
		r = cast[0]
	}
	return xmlToMap(xmlVal, r)
}
func NewMapXmlReader(xmlReader io.Reader, cast ...bool) (Map, error) {
	var r bool
	if len(cast) == 1 {
		r = cast[0]
	}
	if _, ok := xmlReader.(io.ByteReader); !ok {
		xmlReader = myByteReader(xmlReader)  
	}
	return xmlReaderToMap(xmlReader, r)
}
func NewMapXmlReaderRaw(xmlReader io.Reader, cast ...bool) (Map, []byte, error) {
	var r bool
	if len(cast) == 1 {
		r = cast[0]
	}
	buf := make([]byte, 0)
	wb := bytes.NewBuffer(buf)
	trdr := myTeeReader(xmlReader, wb)  
	m, err := xmlReaderToMap(trdr, r)
	b := wb.Bytes()
	if err != nil {
		return nil, b, err
	}
	return m, b, nil
}
func xmlReaderToMap(rdr io.Reader, r bool) (map[string]interface{}, error) {
	p := xml.NewDecoder(rdr)
	if CustomDecoder != nil {
		useCustomDecoder(p)
	} else {
		p.CharsetReader = XmlCharsetReader
	}
	return xmlToMapParser("", nil, p, r)
}
func xmlToMap(doc []byte, r bool) (map[string]interface{}, error) {
	b := bytes.NewReader(doc)
	p := xml.NewDecoder(b)
	if CustomDecoder != nil {
		useCustomDecoder(p)
	} else {
		p.CharsetReader = XmlCharsetReader
	}
	return xmlToMapParser("", nil, p, r)
}
func PrependAttrWithHyphen(v bool) {
	if v {
		attrPrefix = "-"
		lenAttrPrefix = len(attrPrefix)
		return
	}
	attrPrefix = ""
	lenAttrPrefix = len(attrPrefix)
}
var includeTagSeqNum bool
func IncludeTagSeqNum(b ...bool) {
	if len(b) == 0 {
		includeTagSeqNum = !includeTagSeqNum
	} else if len(b) == 1 {
		includeTagSeqNum = b[0]
	}
}
var lowerCase bool
func CoerceKeysToLower(b ...bool) {
	if len(b) == 0 {
		lowerCase = !lowerCase
	} else if len(b) == 1 {
		lowerCase = b[0]
	}
}
var disableTrimWhiteSpace bool
var trimRunes = "\t\r\b\n "
func DisableTrimWhiteSpace(b ...bool) {
	if len(b) == 0 {
		disableTrimWhiteSpace = true
	} else {
		disableTrimWhiteSpace = b[0]
	}
	if disableTrimWhiteSpace {
		trimRunes = "\t\r\b\n"
	} else {
		trimRunes = "\t\r\b\n "
	}
}
var attrPrefix string = `-`  
var lenAttrPrefix int = 1    
func SetAttrPrefix(s string) {
	attrPrefix = s
	lenAttrPrefix = len(attrPrefix)
}
var snakeCaseKeys bool
func CoerceKeysToSnakeCase(b ...bool) {
	if len(b) == 0 {
		snakeCaseKeys = !snakeCaseKeys
	} else if len(b) == 1 {
		snakeCaseKeys = b[0]
	}
}
var castToInt bool
func CastValuesToInt(b ...bool) {
	if len(b) == 0 {
		castToInt = !castToInt
	} else if len(b) == 1 {
		castToInt = b[0]
	}
}
var handleXMPPStreamTag bool
func HandleXMPPStreamTag(b ...bool) {
	if len(b) == 0 {
		handleXMPPStreamTag = !handleXMPPStreamTag
	} else if len(b) == 1 {
		handleXMPPStreamTag = b[0]
	}
}
var decodeSimpleValuesAsMap bool
func DecodeSimpleValuesAsMap(b ...bool) {
	if len(b) == 0 {
		decodeSimpleValuesAsMap = !decodeSimpleValuesAsMap
	} else if len(b) == 1 {
		decodeSimpleValuesAsMap = b[0]
	}
}
func xmlToMapParser(skey string, a []xml.Attr, p *xml.Decoder, r bool) (map[string]interface{}, error) {
	if lowerCase {
		skey = strings.ToLower(skey)
	}
	if snakeCaseKeys {
		skey = strings.Replace(skey, "-", "_", -1)
	}
	var n, na map[string]interface{}
	var seq int  
	if skey != "" {
		n = make(map[string]interface{})   
		na = make(map[string]interface{})  
		if len(a) > 0 {
			for _, v := range a {
				if snakeCaseKeys {
					v.Name.Local = strings.Replace(v.Name.Local, "-", "_", -1)
				}
				var key string
				key = attrPrefix + v.Name.Local
				if lowerCase {
					key = strings.ToLower(key)
				}
				if xmlEscapeCharsDecoder {  
					v.Value = escapeChars(v.Value)
				}
				na[key] = cast(v.Value, r, key)
			}
		}
	}
	if handleXMPPStreamTag && skey == "stream" {
		n[skey] = na
		return n, nil
	}
	for {
		t, err := p.Token()
		if err != nil {
			if err != io.EOF {
				return nil, errors.New("xml.Decoder.Token() - " + err.Error())
			}
			return nil, err
		}
		switch t.(type) {
		case xml.StartElement:
			tt := t.(xml.StartElement)
			if skey == "" {
				return xmlToMapParser(tt.Name.Local, tt.Attr, p, r)
			}
			nn, err := xmlToMapParser(tt.Name.Local, tt.Attr, p, r)
			if err != nil {
				return nil, err
			}
			var key string
			var val interface{}
			for key, val = range nn {
				break
			}
			if includeTagSeqNum {
				switch val.(type) {
				case []interface{}:
				case map[string]interface{}:
					val.(map[string]interface{})["_seq"] = seq  
					seq++
				case interface{}:  
					v := map[string]interface{}{"#text": val}
					v["_seq"] = seq
					seq++
					val = v
				}
			}
			if v, ok := na[key]; ok {
				var a []interface{}
				switch v.(type) {
				case []interface{}:
					a = v.([]interface{})
				default:  
					a = []interface{}{v}
				}
				a = append(a, val)
				na[key] = a
			} else {
				na[key] = val  
			}
		case xml.EndElement:
			if len(n) == 0 {
				if len(na) > 0 {
					n[skey] = na
				} else {
					n[skey] = ""  
				}
			} else if len(n) == 1 && len(na) > 0 {
				for _, v := range n {
					na["#text"] = v
				}
				n[skey] = na
			}
			return n, nil
		case xml.CharData:
			tt := strings.Trim(string(t.(xml.CharData)), trimRunes)
			if xmlEscapeCharsDecoder {  
				tt = escapeChars(tt)
			}
			if len(tt) > 0 {
				if len(na) > 0 || decodeSimpleValuesAsMap {
					na["#text"] = cast(tt, r, "#text")
				} else if skey != "" {
					n[skey] = cast(tt, r, skey)
				} else {
					continue
				}
			}
		default:
		}
	}
}
var castNanInf bool
func CastNanInf(b ...bool) {
	if len(b) == 0 {
		castNanInf = !castNanInf
	} else if len(b) == 1 {
		castNanInf = b[0]
	}
}
func cast(s string, r bool, t string) interface{} {
	if checkTagToSkip != nil && t != "" && checkTagToSkip(t) {
		return s
	}
	if r {
		if !castNanInf {
			switch strings.ToLower(s) {
			case "nan", "inf", "-inf":
				return s
			}
		}
		if castToInt {
			if f, err := strconv.ParseInt(s, 10, 64); err == nil {
				return f
			}
			if f, err := strconv.ParseUint(s, 10, 64); err == nil {
				return f
			}
		}
		if castToFloat {
			if f, err := strconv.ParseFloat(s, 64); err == nil {
				return f
			}
		}
		if castToBool {
			if len(s) > 0 && len(s) < 6 {
				switch s[:1] {
				case "t", "T", "f", "F":
					if b, err := strconv.ParseBool(s); err == nil {
						return b
					}
				}
			}
		}
	}
	return s
}
var castToFloat = true
func CastValuesToFloat(b ...bool) {
	if len(b) == 0 {
		castToFloat = !castToFloat
	} else if len(b) == 1 {
		castToFloat = b[0]
	}
}
var castToBool = true
func CastValuesToBool(b ...bool) {
	if len(b) == 0 {
		castToBool = !castToBool
	} else if len(b) == 1 {
		castToBool = b[0]
	}
}
var checkTagToSkip func(string) bool
func SetCheckTagToSkipFunc(fn func(string) bool) {
	checkTagToSkip = fn
}
const (
	DefaultRootTag = "doc"
)
var useGoXmlEmptyElemSyntax bool
func XmlGoEmptyElemSyntax() {
	useGoXmlEmptyElemSyntax = true
}
func XmlDefaultEmptyElemSyntax() {
	useGoXmlEmptyElemSyntax = false
}
var xmlCheckIsValid bool
func XmlCheckIsValid(b ...bool) {
	if len(b) == 1 {
		xmlCheckIsValid = b[0]
		return
	}
	xmlCheckIsValid = !xmlCheckIsValid
}
func (mv Map) Xml(rootTag ...string) ([]byte, error) {
	m := map[string]interface{}(mv)
	var err error
	b := new(bytes.Buffer)
	p := new(pretty)  
	if len(m) == 1 && len(rootTag) == 0 {
		for key, value := range m {
			switch value.(type) {
			case []interface{}:
				for _, v := range value.([]interface{}) {
					switch v.(type) {
					case map[string]interface{}:  
					default:  
						err = marshalMapToXmlIndent(false, b, DefaultRootTag, m, p)
						goto done
					}
				}
			}
			err = marshalMapToXmlIndent(false, b, key, value, p)
		}
	} else if len(rootTag) == 1 {
		err = marshalMapToXmlIndent(false, b, rootTag[0], m, p)
	} else {
		err = marshalMapToXmlIndent(false, b, DefaultRootTag, m, p)
	}
done:
	if xmlCheckIsValid {
		d := xml.NewDecoder(bytes.NewReader(b.Bytes()))
		for {
			_, err = d.Token()
			if err == io.EOF {
				err = nil
				break
			} else if err != nil {
				return nil, err
			}
		}
	}
	return b.Bytes(), err
}
func (mv Map) XmlWriter(xmlWriter io.Writer, rootTag ...string) error {
	x, err := mv.Xml(rootTag...)
	if err != nil {
		return err
	}
	_, err = xmlWriter.Write(x)
	return err
}
func (mv Map) XmlIndentWriter(xmlWriter io.Writer, prefix, indent string, rootTag ...string) error {
	x, err := mv.XmlIndent(prefix, indent, rootTag...)
	if err != nil {
		return err
	}
	_, err = xmlWriter.Write(x)
	return err
}
var xhandlerPollInterval = time.Millisecond