code: private String readAttType() throws Exception {
          if (tryRead('(')) {
              parseEnumeration(false);
              return "ENUMERATION";
          } else {
              String typeString = readNmtoken(true);
              if (handler.stringInterning) {
                  if ("NOTATION" == typeString) {
                      parseNotationType();
                      return typeString;
                  } else if (("CDATA" == typeString) || ("ID" == typeString)
                          || ("IDREF" == typeString) || ("IDREFS" == typeString)
                          || ("ENTITY" == typeString) || ("ENTITIES" == typeString)
                          || ("NMTOKEN" == typeString) || ("NMTOKENS" == typeString)) {
                      return typeString;
                  }
              } else {
                  if ("NOTATION".equals(typeString)) {
                      parseNotationType();
                      return typeString;
                  } else if ("CDATA".equals(typeString)
                          || "ID".equals(typeString)
                          || "IDREF".equals(typeString)
                          || "IDREFS".equals(typeString)
                          || "ENTITY".equals(typeString)
                          || "ENTITIES".equals(typeString)
                          || "NMTOKEN".equals(typeString)
                          || "NMTOKENS".equals(typeString)) {
                      return typeString;
                  }
              }
              fatal("illegal attribute type", typeString, null);
              return null;
          }
      }
docs: Parse the attribute type.
  
  <pre>
  [54] AttType ::= StringType | TokenizedType | EnumeratedType
  [55] StringType ::= 'CDATA'
  [56] TokenizedType ::= 'ID' | 'IDREF' | 'IDREFS' | 'ENTITY'
  | 'ENTITIES' | 'NMTOKEN' | 'NMTOKENS'
  [57] EnumeratedType ::= NotationType | Enumeration
  </pre>