private class CommaHandler extends AdapterHandler {
    private BufferedWriter m_out;
    private int m_depth = 0;
    private StringBuffer m_text = null;
    private boolean m_first = true;

    public CommaHandler(OutputStream out) {
        m_out = new BufferedWriter(new OutputStreamWriter(out));
    }

    public void startElement(String uri, String local, String qName, Attributes atts)
        throws SAXException {
        m_depth++;
        if (m_depth == 2) // start row
            m_first = true;
        else
        if (m_depth == 3) // start column
            m_text = new StringBuffer();
    }

    public void endElement(String uri, String local, String qName)
        throws SAXException {
        if (m_depth == 2) { // finish row
            try {
                m_out.write(getEndOfLine());
            } catch (IOException ioe) {
                exception(ioe);
            }
        }
        else
        if (m_depth == 3) { // finish column
            String text = m_text.toString();
            if (text.indexOf(m_comma) != -1
                || text.indexOf('"') != -1
                || text.indexOf('\'') != -1) {
                if (text.indexOf('"') != -1)
                    text = text.replaceAll("\"", "\"\"");
                text = '"' + text + '"';
            }

            try {
                if (!m_first)
                    m_out.write(m_comma);
                m_out.write(text);
            } catch (IOException ioe) {
                exception(ioe);
            }

            m_first = false;
            m_text = null;
        }
        m_depth--;
    }

    public void characters(char[] text, int start, int length)
        throws SAXException {
        if (m_text != null)
            m_text.append(text, start, length);
    }

    public void endDocument() throws SAXException {
        try {
            m_out.flush();
        }
        catch (IOException ioe) {
            exception(ioe);
        }
    }
}