code: private String _serializeQuery(Query query, Set<Object> done) throws ConverterException {
  
  	// fieldnames
  	PageContext pc = ThreadLocalPageContext.get();
  	boolean upperCase = false;
  	if (pc != null) upperCase = pc.getCurrentTemplateDialect() == CFMLEngine.DIALECT_CFML && !((ConfigWebImpl) pc.getConfig()).preserveCase();
  
  	StringBuilder fn = new StringBuilder();
  	Collection.Key[] keys = CollectionUtil.keys(query);
  	for (int i = 0; i < keys.length; i++) {
  	    if (i > 0) fn.append(',');
  	    fn.append(XMLUtil.escapeXMLString(upperCase ? keys[i].getUpperString() : keys[i].getString()));
  	}
  
  	StringBuilder sb = new StringBuilder(
  		goIn() + "<recordset rowCount=" + del + query.getRecordcount() + del + " fieldNames=" + del + fn + del + " type=" + del + "coldfusion.sql.QueryTable" + del + ">");
  
  	deep++;
  	int len = query.getRecordcount();
  	for (int i = 0; i < keys.length; i++) {
  	    sb.append(goIn() + "<field name=" + del + XMLUtil.escapeXMLString(keys[i].getString()) + del + ">");
  	    for (int y = 1; y <= len; y++) {
  		try {
  		    sb.append(_serialize(query.getAt(keys[i], y), done));
  		}
  		catch (PageException e) {
  		    sb.append(_serialize(e.getMessage(), done));
  		}
  	    }
  
  	    sb.append(goIn() + "</field>");
  	}
  	deep--;
  
  	sb.append(goIn() + "</recordset>");
  	return sb.toString();
      }
docs: serialize a Query
  
  @param query Query to serialize
  @param done
  @return serialized query
  @throws ConverterException