func XmlMsgsFromReader(rdr io.Reader, phandler func(map[string]interface{})(bool), ehandler func(error)(bool), recast ...bool) error {
	var r bool
	if len(recast) == 1 {
		r = recast[0]
	}
	for {
		m, merr := ToMap(rdr,r)
		if merr != nil && merr != io.EOF {
			if ok := ehandler(merr); !ok {
				return merr
			 }
		}
		if m != nil {
			if ok := phandler(m); !ok {
				break
			}
		}
		if merr == io.EOF {
			break
		}
	}
	return nil
}
=============================  io.Reader version for stream processing  ======================
XmlMsgsFromReader() - io.Reader version of XmlMsgsFromFile
'rdr' is an io.Reader for an XML message (stream)
'phandler' is the map processing handler. Return of 'false' stops further processing.
'ehandler' is the parsing error handler. Return of 'false' stops further processing and returns error.
Note: phandler() and ehandler() 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 arguments to a go routine in handler and return true.
package x2j
import (
	"bytes"
	"encoding/xml"
	"errors"
	"io"
	"os"
	"regexp"
	"sync"
)
func XmlMsgsFromFile(fname string, phandler func(map[string]interface{})(bool), ehandler func(error)(bool), recast ...bool) error {
	var r bool
	if len(recast) == 1 {
		r = recast[0]
	}
	fi, fierr := os.Stat(fname)
	if fierr != nil {
		return fierr
	}
	fh, fherr := os.Open(fname)
	if fherr != nil {
		return fherr
	}
	defer fh.Close()
	buf := make([]byte,fi.Size())
	_, rerr  :=  fh.Read(buf)
	if rerr != nil {
		return rerr
	}
	doc := string(buf)
	reg,_ := regexp.Compile("[ \t\n\r]*<")
	doc = reg.ReplaceAllString(doc,"<")
	b := bytes.NewBufferString(doc)
	for {
		m, merr := XmlBufferToMap(b,r)
		if merr != nil && merr != io.EOF {
			if ok := ehandler(merr); !ok {
				return merr
			 }
		}
		if m != nil {
			if ok := phandler(m); !ok {
				break
			}
		}
		if merr == io.EOF {
			break
		}
	}
	return nil
}
func XmlBufferToMap(b *bytes.Buffer,recast ...bool) (map[string]interface{},error) {
	var r bool
	if len(recast) == 1 {
		r = recast[0]
	}
	n,err := XmlBufferToTree(b)
	if err != nil {
		return nil, err
	}
	m := make(map[string]interface{})
	m[n.key] = n.treeToMap(r)
	return m,nil
}
func XmlBufferToTree(b *bytes.Buffer) (*Node, error) {
	p := xml.NewDecoder(b)
	p.CharsetReader = X2jCharsetReader
	n, berr := xmlToTree("",nil,p)
	if berr != nil {
		return nil, berr
	}
	return n,nil
}
type XmlBuffer struct {
	cnt uint64
	str *string
	buf *bytes.Buffer
}
var mtx sync.Mutex
var cnt uint64
var activeXmlBufs = make(map[uint64]*XmlBuffer)
func NewXmlBuffer(s string) *XmlBuffer {
	reg,_ := regexp.Compile("[ \t\n\r]*<")
	s = reg.ReplaceAllString(s,"<")
	b := bytes.NewBufferString(s)
	buf := new(XmlBuffer)
	buf.str = &s
	buf.buf = b
	mtx.Lock()
	defer mtx.Unlock()
	buf.cnt = cnt ; cnt++
	activeXmlBufs[buf.cnt] = buf
	return buf
}
func BytesNewXmlBuffer(b []byte) *XmlBuffer {
	bb := bytes.NewBuffer(b)
	buf := new(XmlBuffer)
	buf.buf = bb
	mtx.Lock()
	defer mtx.Unlock()
	buf.cnt = cnt ; cnt++
	activeXmlBufs[buf.cnt] = buf
	return buf
}
func (buf *XmlBuffer)Close() {
	mtx.Lock()
	defer mtx.Unlock()
	delete(activeXmlBufs,buf.cnt)
}
func (buf *XmlBuffer)NextMap(recast ...bool) (map[string]interface{}, error) {
		var r bool
		if len(recast) == 1 {
			r = recast[0]
		}
		if _, ok := activeXmlBufs[buf.cnt]; !ok {
			return nil, errors.New("Buffer is not active.")
		}
		return XmlBufferToMap(buf.buf,r)
}