Streaming solutions are often more efficent
That's a big reason to use SAX instead of DOM
import java.sql.*; import java.io.*; public class BiosToReader implements Runnable { private Writer out; private Reader source; public Reader getReader() { return this.source; } private String userName; private String password; // should be a char[] for security private String host = "luna.oit.unc.edu"; private String database = "NYWC"; public BiosToReader(String userName, String password) throws IOException { this.userName = userName; this.password = password; PipedWriter out = new PipedWriter(); this.source = new PipedReader(out); this.out = out; } //Requires JDBC MySQL Driver from http://www.worldserver.com/mm.mysql/ private String driver = "org.gjt.mm.mysql.Driver"; public void run() { try { Class.forName(driver).newInstance(); // Connect to the database Connection connection = DriverManager.getConnection( "jdbc:mysql://" + host + "/" + database, userName, password); Statement statement = connection.createStatement(); ResultSet bios = statement.executeQuery( "SELECT * FROM composers ORDER BY ComposerLastName, ComposerFirstName"); out.write("<?xml version=\"1.0\"?>\r\n"); out.write("<Composers>\r\n"); while (bios.next()) { out.write(" <Composer>\r\n"); /* primary key */ out.write(" <first>"); out.write(bios.getString("ComposerFirstName")); out.write("</first>\r\n"); out.write(" <middle>"); out.write(bios.getString("ComposerMiddleName")); out.write("</middle>\r\n"); out.write(" <name>\r\n"); out.write(" <last>"); out.write(bios.getString("ComposerLastName")); out.write("</last>\r\n"); out.write(" </name>\r\n"); /* These can be null */ writeElement("biography", bios.getString("ComposerBio")); writeElement("email", bios.getString("ComposerEmail")); writeElement("url", bios.getString("ComposerURL")); writeElement("title", bios.getString("ComposerTitle")); // Omit these for privacy in this example /* writeElement("voice", bios.getString("ComposerVoice")); writeElement("fax", bios.getString("ComposerFax")); writeElement("street", bios.getString("ComposerStreet")); writeElement("suite", bios.getString("ComposerSuite")); */ writeElement("state", bios.getString("ComposerState")); writeElement("city", bios.getString("ComposerCity")); writeElement("country", bios.getString("ComposerCountry")); writeElement("zip", bios.getString("ComposerZip")); Date expires = bios.getDate("ComposerMembershipExpires"); String expiresDate = null; if (expires != null) expiresDate = expires.toString(); writeElement("expires", expiresDate); out.write(" </Composer>\r\n\r\n"); } out.write("</Composers>\r\n"); out.flush(); } catch (Exception e) { System.err.println(e); e.printStackTrace(); } } private void writeElement(String name, String content) throws IOException { // would be straight-forward to omit null elements // rather than making them empty out.write('<' + name + '>'); if (content != null) { char[] characters = content.toCharArray(); for (int i = 0; i < characters.length; i++) { switch (characters[i]) { case '&': out.write("&"); break; case '<': out.write("<"); break; default: out.write(characters[i]); } } } out.write("</" + name + ">\r\n"); } public static void main(String[] args) { try { BiosToReader btr = new BiosToReader(args[0], args[1]); Thread t = new Thread(btr); t.start(); Reader in = btr.getReader(); int c; try { while ((c = in.read()) != -1) System.out.write(c); } catch (IOException e) { // Write end dead } } catch (ArrayIndexOutOfBoundsException e) { System.out.println("Usage: java BiosToReader username password"); } catch (Exception e) { System.err.println(e); e.printStackTrace(); } } }