void toXml(PrintStream s) {

		try {
			s.println("\t<rra>");
			s.print("\t\t<cf> ");
			s.print(type);
			s.println(" </cf>");
			s.print("\t\t<pdp_per_row> ");
			s.print(pdpCount);
			s.print(" </pdp_per_row> <!-- ");
			s.print(db.header.pdpStep * pdpCount);
			s.println(" seconds -->");
			s.print("\t\t<xff> ");
			s.print(xff);
			s.println(" </xff>");
			s.println();
			s.println("\t\t<cdp_prep>");

			for (int i = 0; i < cdpStatusBlocks.size(); i++) {
				((CDPStatusBlock) cdpStatusBlocks.get(i)).toXml(s);
			}

			s.println("\t\t</cdp_prep>");
			s.println("\t\t<database>");

			long timer = -(rowCount - 1);
			int counter = 0;
			int row = currentRow;

			db.rrdFile.ras.seek(dataOffset + (row + 1) * 16);

			long lastUpdate = db.lastUpdate.getTime() / 1000;
			int pdpStep = db.header.pdpStep;
			NumberFormat numberFormat = new DecimalFormat("0.0000000000E0");
			SimpleDateFormat dateFormat =
					new SimpleDateFormat("yyyy-MM-dd HH:mm:ss z");

			while (counter++ < rowCount) {
				row++;

				if (row == rowCount) {
					row = 0;

					db.rrdFile.ras.seek(dataOffset);
				}

				long now = (lastUpdate - lastUpdate % (pdpCount * pdpStep))
						+ (timer * pdpCount * pdpStep);

				timer++;

				s.print("\t\t\t<!-- ");
				s.print(dateFormat.format(new Date(now * 1000)));
				s.print(" / ");
				s.print(now);
				s.print(" --> ");

				for (int col = 0; col < db.header.dsCount; col++) {
					s.print("<v> ");

					double value = db.rrdFile.readDouble();

					// NumberFormat doesn't know how to handle NaN
					if (Double.isNaN(value)) {
						s.print("NaN");
					} else {
						s.print(numberFormat.format(value));
					}

					s.print(" </v>");
				}

				s.println("</row>");
			}

			s.println("\t\t</database>");
			s.println("\t</rra>");
		} catch (IOException e) {    // Is the best thing to do here?
			throw new RuntimeException(e.getMessage());
		}
	}