public void save() throws IOException {
        try {
            // Generate XML builder
            // (thanks to
            // http://www.mkyong.com/java/how-to-create-xml-file-in-java-dom/)
            DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
            DocumentBuilder docBuilder = docFactory.newDocumentBuilder();
            Document doc = docBuilder.newDocument();
            
            // Required element level objects
            Element e0, e1, e2, e3, e4, e5;
            
            // <favourites>
            e0 = doc.createElement("favourites");
            for (Favourite f : list) {
                // <favourite name="">
                e1 = doc.createElement("favourite");
                e1.setAttribute("name", f.getName());
                // <algorithm name="">
                e2 = doc.createElement("algorithm");
                e2.setAttribute("name", f.getAlgorithm().getName());
                // <iterations>
                e3 = doc.createElement("iterations");
                e3.appendChild(doc.createTextNode(f.getAlgorithm().getIterations() + ""));
                e2.appendChild(e3);
                // <escaperadius>
                e3 = doc.createElement("escaperadius");
                e3.appendChild(doc.createTextNode(f.getAlgorithm().getEscapeRadius() + ""));
                e2.appendChild(e3);
                // </algorithm>
                e1.appendChild(e2);
                // <selected>
                e2 = doc.createElement("selected");
                // <real>
                e3 = doc.createElement("real");
                e3.appendChild(doc.createTextNode(f.getSelected().real() + ""));
                e2.appendChild(e3);
                // <imaginary>
                e3 = doc.createElement("imaginary");
                e3.appendChild(doc.createTextNode(f.getSelected().imaginary() + ""));
                e2.appendChild(e3);
                // </selected>
                // <bounds>
                e2 = doc.createElement("bounds");
                // <bottomleft>
                e3 = doc.createElement("bottomleft");
                // <real>
                e4 = doc.createElement("real");
                e4.appendChild(doc.createTextNode(f.getBounds()[0].real() + ""));
                e3.appendChild(e4);
                // <imaginary>
                e4 = doc.createElement("imaginary");
                e4.appendChild(doc.createTextNode(f.getBounds()[0].imaginary() + ""));
                e3.appendChild(e4);
                e2.appendChild(e3);
                // </bottomleft>
                // <topright>
                e3 = doc.createElement("topright");
                // <real>
                e4 = doc.createElement("real");
                e4.appendChild(doc.createTextNode(f.getBounds()[1].real() + ""));
                e3.appendChild(e4);
                // <imaginary>
                e4 = doc.createElement("imaginary");
                e4.appendChild(doc.createTextNode(f.getBounds()[1].imaginary() + ""));
                e3.appendChild(e4);
                // </topright>
                e2.appendChild(e3);
                // </bounds>
                e1.appendChild(e2);
                // <scheme>
                e2 = doc.createElement("scheme");
                // <gridlines>
                e3 = doc.createElement("gridlines");
                e3.appendChild(doc.createTextNode(serialiseColour(f.getScheme().getGridlineColour())));
                e2.appendChild(e3);
                // <colours>
                e3 = doc.createElement("colours");
                for (Map.Entry<Double, Color> entry : f.getScheme().entrySet()) {
                    // <colourstop>
                    e4 = doc.createElement("colourstop");
                    // <progress>
                    e5 = doc.createElement("progress");
                    e5.appendChild(doc.createTextNode(entry.getKey() + ""));
                    e4.appendChild(e5);
                    // <colour>
                    e5 = doc.createElement("colour");
                    e5.appendChild(doc.createTextNode(serialiseColour(entry.getValue())));
                    e4.appendChild(e5);
                    // </colourstop>
                    e3.appendChild(e4);
                }
                // </colours>
                e2.appendChild(e3);
                // </scheme>
                e1.appendChild(e2);
                // </favourite>
                e0.appendChild(e1);
            }
            // </favourites>
            doc.appendChild(e0);
            
            // Request a cleanup of all those objects now
            System.gc();
            
            // Prepare Optimus Prime
            TransformerFactory transformerFactory = TransformerFactory.newInstance();
            Transformer transformer = transformerFactory.newTransformer();
            transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "no");
            transformer.setOutputProperty(OutputKeys.METHOD, "xml");
            transformer.setOutputProperty(OutputKeys.INDENT, "yes");
            transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8");
            transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "4");
            
            // Write output
            DOMSource source = new DOMSource(doc);
            StreamResult result = new StreamResult(filename);
            transformer.transform(source, result);
            
        } catch (Exception ex) {
            // Re-throw XML generation exceptions as IOExceptions
            if (ex instanceof IOException)
                throw (IOException) ex;
            else
                throw new IOException(ex);
        }
    }