private String readNmtoken(boolean isName) throws SAXException, IOException {
        char c;

        nameBufferPos = 0;

        // Read the first character.
        while (true) {
            c = readCh();
            switch (c) {
                case '%':
                case '<':
                case '>':
                case '&':
                case ',':
                case '|':
                case '*':
                case '+':
                case '?':
                case ')':
                case '=':
                case '\'':
                case '"':
                case '[':
                case ' ':
                case '\t':
                case '\n':
                case '\r':
                case ';':
                case '/':
                    unread(c);
                    if (nameBufferPos == 0) {
                        fatal("name expected");
                    }
                    String s = intern(nameBuffer, 0, nameBufferPos);
                    nameBufferPos = 0;
                    return s;
                default:
                    if (isName && (nameBufferPos == 0)
                            && (!(NCName.isNCNameStart(c)))) {
                        fatal("Not a name start character, U+"
                                + Integer.toHexString(c));
                    } else if (!(NCName.isNCNameTrail(c) || c == ':')) {
                        fatal("Not a name character, U+"
                                + Integer.toHexString(c));
                    }
                    if (nameBufferPos >= nameBuffer.length) {
                        nameBuffer = (char[]) extendArray(nameBuffer,
                                nameBuffer.length, nameBufferPos);
                    }
                    nameBuffer[nameBufferPos++] = c;
            }
        }
    }
Read a name or (when parsing an enumeration) name token.

<pre>
  [5] Name ::= (Letter | '_' | ':') (NameChar)*
  [7] Nmtoken ::= (NameChar)+
</pre>
src/nu/validator/gnu/xml/aelfred2/XmlParser.java