func IsValidSchemaURI(uri string) bool {
	return len(uri) > 0 &&
		utf8.ValidString(uri) &&
		strings.IndexFunc(uri, invalidSchemaRune) == -1
}
IsValidSchemaURI reports whether the given argument is suitable for
use as a namespace schema URI. It must be non-empty, a valid UTF-8
string and it must not contain white space.
package checkers
import (
	"sort"
	"strings"
	"unicode"
	"unicode/utf8"
	errgo "gopkg.in/errgo.v1"
)
type Namespace struct {
	uriToPrefix map[string]string
}
func NewNamespace(uriToPrefix map[string]string) *Namespace {
	ns := &Namespace{
		uriToPrefix: make(map[string]string),
	}
	for uri, prefix := range uriToPrefix {
		ns.Register(uri, prefix)
	}
	return ns
}
func (ns *Namespace) String() string {
	data, _ := ns.MarshalText()
	return string(data)
}
func (ns *Namespace) MarshalText() ([]byte, error) {
	if ns == nil || len(ns.uriToPrefix) == 0 {
		return nil, nil
	}
	uris := make([]string, 0, len(ns.uriToPrefix))
	dataLen := 0
	for uri, prefix := range ns.uriToPrefix {
		uris = append(uris, uri)
		dataLen += len(uri) + 1 + len(prefix) + 1
	}
	sort.Strings(uris)
	data := make([]byte, 0, dataLen)
	for i, uri := range uris {
		if i > 0 {
			data = append(data, ' ')
		}
		data = append(data, uri...)
		data = append(data, ':')
		data = append(data, ns.uriToPrefix[uri]...)
	}
	return data, nil
}
func (ns *Namespace) UnmarshalText(data []byte) error {
	uriToPrefix := make(map[string]string)
	elems := strings.Fields(string(data))
	for _, elem := range elems {
		i := strings.LastIndex(elem, ":")
		if i == -1 {
			return errgo.Newf("no colon in namespace field %q", elem)
		}
		uri, prefix := elem[0:i], elem[i+1:]
		if !IsValidSchemaURI(uri) {
			return errgo.Newf("invalid URI %q in namespace field %q", uri, elem)
		}
		if !IsValidPrefix(prefix) {
			return errgo.Newf("invalid prefix %q in namespace field %q", prefix, elem)
		}
		if _, ok := uriToPrefix[uri]; ok {
			return errgo.Newf("duplicate URI %q in namespace %q", uri, data)
		}
		uriToPrefix[uri] = prefix
	}
	ns.uriToPrefix = uriToPrefix
	return nil
}
func (ns *Namespace) EnsureResolved(uri string) (string, bool) {
	return ns.Resolve(uri)
}
func (ns *Namespace) Resolve(uri string) (string, bool) {
	if ns == nil {
		return "", false
	}
	prefix, ok := ns.uriToPrefix[uri]
	return prefix, ok
}
func (ns *Namespace) ResolveCaveat(cav Caveat) Caveat {
	if cav.Namespace == "" || cav.Location != "" {
		return cav
	}
	prefix, ok := ns.Resolve(cav.Namespace)
	if !ok {
		errCav := ErrorCaveatf("caveat %q in unregistered namespace %q", cav.Condition, cav.Namespace)
		if errCav.Namespace != cav.Namespace {
			prefix, _ = ns.Resolve(errCav.Namespace)
		}
		cav = errCav
	}
	if prefix != "" {
		cav.Condition = ConditionWithPrefix(prefix, cav.Condition)
	}
	cav.Namespace = ""
	return cav
}
func ConditionWithPrefix(prefix, condition string) string {
	if prefix == "" {
		return condition
	}
	return prefix + ":" + condition
}
func (ns *Namespace) Register(uri, prefix string) {
	if !IsValidSchemaURI(uri) {
		panic(errgo.Newf("cannot register invalid URI %q (prefix %q)", uri, prefix))
	}
	if !IsValidPrefix(prefix) {
		panic(errgo.Newf("cannot register invalid prefix %q for URI %q", prefix, uri))
	}
	if _, ok := ns.uriToPrefix[uri]; !ok {
		ns.uriToPrefix[uri] = prefix
	}
}
func invalidSchemaRune(r rune) bool {
	return unicode.IsSpace(r)
}