* @throws SAXException
   *           if an exception is thrown by the ContentHandler
   */
  public static void typeSystem2Xml(TypeSystem aTypeSystem, ContentHandler aContentHandler)
          throws SAXException {
    ResourceSpecifierFactory factory = UIMAFramework.getResourceSpecifierFactory();
    TypeSystemDescription tsDesc = factory.createTypeSystemDescription();
    List<TypeDescription> typeDescs = new ArrayList<TypeDescription>();
    Iterator<Type> typeIterator = aTypeSystem.getTypeIterator();
    while (typeIterator.hasNext()) {
      Type type = typeIterator.next();
      Type superType = aTypeSystem.getParent(type);
      if ((type.getName().startsWith("uima.cas") && type.isFeatureFinal()) || type.isArray()) {
        continue; // this indicates a primitive type
      }
      TypeDescription typeDesc = factory.createTypeDescription();
      typeDesc.setName(type.getName());
      typeDesc.setSupertypeName(superType.getName());
      LowLevelTypeSystem llts = aTypeSystem.getLowLevelTypeSystem();
      List<FeatureDescription> featDescs = new ArrayList<FeatureDescription>();
      Iterator<Feature> featIterator = type.getFeatures().iterator();
      while (featIterator.hasNext()) {
        Feature feat = featIterator.next();
        if (!feat.getDomain().equals(type)) {
          // Each feature only needs to be serialized once
          continue;
        }
        FeatureDescription featDesc = factory.createFeatureDescription();
        featDesc.setName(feat.getShortName());
        Type rangeType = feat.getRange();
        if (rangeType.isArray()) {
          final int typeClass = llts.ll_getTypeClass(llts.ll_getCodeForType(rangeType));
          String typeName = null;
          switch (typeClass) {
          case LowLevelCAS.TYPE_CLASS_BOOLEANARRAY: {
            typeName = CAS.TYPE_NAME_BOOLEAN_ARRAY;
            break;
          }
          case LowLevelCAS.TYPE_CLASS_SHORTARRAY: {
            typeName = CAS.TYPE_NAME_SHORT_ARRAY;
            break;
          }
          case LowLevelCAS.TYPE_CLASS_BYTEARRAY: {
            typeName = CAS.TYPE_NAME_BYTE_ARRAY;
            break;
          }
          case LowLevelCAS.TYPE_CLASS_DOUBLEARRAY: {
            typeName = CAS.TYPE_NAME_DOUBLE_ARRAY;
            break;
          }
          case LowLevelCAS.TYPE_CLASS_FLOATARRAY: {
            typeName = CAS.TYPE_NAME_FLOAT_ARRAY;
            break;
          }
          case LowLevelCAS.TYPE_CLASS_FSARRAY: {
            typeName = CAS.TYPE_NAME_FS_ARRAY;
            break;
          }
          case LowLevelCAS.TYPE_CLASS_INTARRAY: {
            typeName = CAS.TYPE_NAME_INTEGER_ARRAY;
            break;
          }
          case LowLevelCAS.TYPE_CLASS_LONGARRAY: {
            typeName = CAS.TYPE_NAME_LONG_ARRAY;
            break;
          }
          case LowLevelCAS.TYPE_CLASS_STRINGARRAY: {
            typeName = CAS.TYPE_NAME_STRING_ARRAY;
            break;
          }
          }
          featDesc.setRangeTypeName(typeName);
          // TODO: make sure this works for arrays of arrays
          featDesc.setElementType(rangeType.getComponentType().getName());
        } else {
          featDesc.setRangeTypeName(feat.getRange().getName());
        }
        featDescs.add(featDesc);
      }
      FeatureDescription[] featDescArr = new FeatureDescription[featDescs.size()];
      featDescs.toArray(featDescArr);
      typeDesc.setFeatures(featDescArr);
      // check for string subtypes
      if (type instanceof StringTypeImpl) {
  LowLevelTypeSystem lts = aTypeSystem.getLowLevelTypeSystem();
  final int typeCode = lts.ll_getCodeForType(type);
        String[] strings = lts.ll_getStringSet(typeCode);
        AllowedValue[] allowedVals = new AllowedValue[strings.length];
        for (int i = 0; i < strings.length; i++) {
          allowedVals[i] = factory.createAllowedValue();
          allowedVals[i].setString(strings[i]);
        }
        typeDesc.setAllowedValues(allowedVals);
      }