func TrimSpace(parents *NodeList, in xml.Token) []xml.Token {
	switch t := in.(type) {
	case xml.CharData:
		return []xml.Token{xml.CharData(bytes.TrimSpace(t))}
	}
	return []xml.Token{in}
}
TrimSpace is a transformer function that replaces CDATA with blank
characters with empty strings
package cxml
import (
	"bytes"
	"encoding/xml"
	"io"
	"github.com/gravitational/trace"
)
type TransformFunc func(parents *NodeList, in xml.Token) []xml.Token
type ConditionFunc func(parents *NodeList, in xml.Token) bool
func TransformXML(decoder *xml.Decoder, encoder *xml.Encoder, fn TransformFunc) error {
	parentNodes := &NodeList{}
	for {
		token, err := decoder.Token()
		if err != nil {
			if err != io.EOF {
				return trace.Wrap(err)
			}
			break
		}
		for _, t := range fn(parentNodes, token) {
			if err := encoder.EncodeToken(t); err != nil {
				return err
			}
		}
		switch e := token.(type) {
		case xml.StartElement:
			parentNodes.Push(e)
		case xml.EndElement:
			parentNodes.Pop()
		}
	}
	encoder.Flush()
	return nil
}
func SetAttribute(e xml.StartElement, name, value string) xml.StartElement {
	for i := range e.Attr {
		if e.Attr[i].Name.Local == name {
			e.Attr[i].Value = value
			return e
		}
	}
	e.Attr = append(e.Attr, xml.Attr{Name: xml.Name{Local: name}, Value: value})
	return e
}
func ReplaceCDATAIf(val xml.CharData, cond ConditionFunc) TransformFunc {
	return func(parents *NodeList, in xml.Token) []xml.Token {
		switch in.(type) {
		case xml.CharData:
			if cond(parents, in) {
				return []xml.Token{val.Copy()}
			}
		}
		return []xml.Token{in}
	}
}
func InjectNodesIf(nodes []xml.Token, cond ConditionFunc) TransformFunc {
	return func(parents *NodeList, in xml.Token) []xml.Token {
		if cond(parents, in) {
			return append(nodes, in)
		}
		return []xml.Token{in}
	}
}
func ReplaceAttributeIf(attrName, attrValue string, cond ConditionFunc) TransformFunc {
	return func(parents *NodeList, in xml.Token) []xml.Token {
		switch t := in.(type) {
		case xml.StartElement:
			if cond(parents, in) {
				e := xml.StartElement(t)
				return []xml.Token{SetAttribute(e, attrName, attrValue)}
			}
		}
		return []xml.Token{in}
	}
}