Index: src/org/biomart/processors/formatters/RDF.java
===================================================================
--- src/org/biomart/processors/formatters/RDF.java	(revision 9838)
+++ src/org/biomart/processors/formatters/RDF.java	(working copy)
@@ -14,7 +14,7 @@
  */
 public class RDF extends TSVFormatter {
 
-    public enum FORMAT { N3 };
+    public enum FORMAT { N3 , RDFXML};
 
     private FORMAT format;
     
@@ -26,6 +26,8 @@
     protected String[] variableTypes;
     protected List<String> columnValues = new LinkedList<String>();
 
+    private int variableNo;
+
     public RDF(OutputStream out,
             String[] variableNames,
             String[] variableProperties,
@@ -47,35 +49,32 @@
                 return;
             }
 
-            //out.write("<?xml version=\"1.0\"?>\n".getBytes());
-
-            if (prelude != null && format != FORMAT.N3)
-                out.write(prelude.getBytes());
-
             this.variableNames = variableNames;
             this.variableProperties = variableProperties;
             this.variableTypes = variableTypes;
             this.visibleColumn = new boolean[variableNames.length];
 
-            //out.write("<sparql xmlns=\"http://www.w3.org/2005/sparql-results#\">\n\t<head>\n".getBytes());
-
-            for (int i = 0, j = 0; i < variableNames.length; i++) {
+            for (int i = 0; i < variableNames.length; i++) {
                 String variableName = variableNames[i];
 
                 if (!variableName.startsWith("?") &&  // Un-projected query variables
                     !variableName.startsWith("!")) {  // Virtual variables for filters
-                    //out.write(("\t\t<variable name=\"" + variableName + "\"/>\n").getBytes());
                     visibleColumn[i] = true;
-                    j = i;
                 }
             }
 
-            //out.write("\t</head>\n\t<results>\n".getBytes());
             switch(format) {
             case N3:
                 for (String prefix : namespaces.keySet())
                     out.write(("@prefix " + prefix + " <" + namespaces.get(prefix) + ">\n").getBytes());
                 break;
+            case RDFXML:
+                out.write("<?xml version=\"1.0\"?>\n".getBytes());
+                out.write("<rdf:RDF\n xmlns:rdfs=\"http://www.w3.org/2000/01/rdf-schema#\"xmlns:rdf=\"http://www.w3.org/1999/02/22-rdf-syntax-ns#\"\n".getBytes());
+                for (String prefix : namespaces.keySet())
+                    out.write((" xmlns:" + prefix + "=" + namespaces.get(prefix) + "\n").getBytes());
+                out.write(" >\n".getBytes());
+                break;
             default:
                 break;
             }
@@ -93,29 +92,76 @@
 
     @Override
     public void writeStartOfLine() throws IOException {
-        //out.write(("\t\t<result>\n").getBytes());
     }
 
     @Override
     public void writeEndOfLine() throws IOException {
-        writeN3();
+        switch(format) {
+        case N3:
+            writeN3();
+            break;
+        default:
+            break;
+        }
     }
     
     @Override
     public void writeField(int column, String value) throws IOException {
-        columnValues.add(value);
+        switch(format) {
+        case N3:
+            columnValues.add(value);
+            break;
+        case RDFXML: // write out each property in its own element
+            if (visibleColumn[column])
+            {
+                // write the opening tag
+                // TODO: seems like we only support blank nodes in results right now                
+                out.write("<rdf:Description rdf:ID=\"\n".getBytes());
+                for (int i = 0; i < variableNames.length; i++) {
+                    String variableName = variableNames[i].replaceFirst("\\?", "");
+                    if (variableTypes[variableNo].equals(variableName))
+                        // write the blank node ID
+                        out.write( columnValues.get(i).getBytes());
+                }
+                out.write("\"><".getBytes());
+                // write the predicate
+                // FIXME: unless this is always prefixed, will need to split it into base and localname and write <localname xmlns="base" instead of this
+                out.write(variableProperties[variableNo].getBytes());
+                out.write(">".getBytes());
+                // write out the actual value as a literal
+                // FIXME: not clear how the N3 version is able to distinguish between URIs, plain literals, typed literals and language literals here
+                out.write(value.getBytes());
+                // write out the end of the property element
+                out.write("</".getBytes());
+                out.write(variableProperties[variableNo].getBytes());
+                out.write(">".getBytes());
+                // write out the end of the line
+                out.write("</rdf:Description>\n".getBytes());
+                variableNo++;
+            }
+            break;
+        default:
+            break;
+        }
     }
     
     @Override
     public void close() throws IOException {
         if (exception) return;
+        
+        switch(format) {
+        case RDFXML:
+            out.write("</rdf:RDF>".getBytes());
+            break;
+        default:
+            break;
+        }
 
-        //out.write("\t</results>\n</sparql>\n".getBytes());
         super.close();
     }
     
     private void writeN3() throws IOException {
-        int variableNo = 0;
+        variableNo = 0;
         
         for (int column = 0; column < visibleColumn.length; column++) {
             if (!visibleColumn[column])
@@ -140,4 +186,5 @@
         
         columnValues.clear();
     }
+    
 }
Index: src/org/biomart/processors/RDFXML.java
===================================================================
--- src/org/biomart/processors/RDFXML.java	(revision 0)
+++ src/org/biomart/processors/RDFXML.java	(revision 0)
@@ -0,0 +1,78 @@
+/**
+ * 
+ */
+package org.biomart.processors;
+
+import java.io.OutputStream;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.biomart.processors.annotations.ContentType;
+import org.jdom.Comment;
+
+import com.google.common.io.Closeables;
+
+/**
+ * 
+ * @author Peter Ansell
+ *
+ */
+@ContentType("application/rdf+xml")
+public class RDFXML extends ProcessorImpl
+{
+    @Override
+    public void setOutputStream(OutputStream out) {
+        String prelude = null;
+        Map<String, String> namespaces = new HashMap<String, String>();
+        String[] variableNames = new String[0];
+        String[] variableProperties = new String[0];
+        String[] variableTypes = new String[0];
+        Map<String, String> variable2URIAttributes = new HashMap<String, String>(); // TODO For now: only one URI attribute supported
+        String exception = null;
+        for (Object content : query.queryXMLobject.getContent()) {
+            if (content instanceof Comment) {
+                Comment comment = (Comment)content;
+
+                // Variable names starting with a "?" are used only internally
+                // and their values are not returned.
+
+                if (comment.getText().startsWith(" VARIABLES:")) {
+                    variableNames = comment.getText().substring(11).trim().split(" ");
+                } else if (comment.getText().startsWith(" VARIABLEPROPERTIES:")) {
+                    variableProperties = comment.getText().substring(20).trim().split(" ");
+                } else if (comment.getText().startsWith(" VARIABLETYPES:")) {
+                    variableTypes = comment.getText().substring(15).trim().split(" ");
+                } else if (comment.getText().startsWith(" NAMESPACE:")) {
+                    String[] prefix2URI = comment.getText().substring(11).trim().split(" ");
+                    namespaces.put(prefix2URI[0], prefix2URI[1]);
+                } else if (comment.getText().startsWith(" NODEATTRIBUTES:")) {
+                    String[] nodeAttributes = comment.getText().substring(16).trim().split(" ");
+                    // TODO For now: only one URI attribute supported
+                    for (String uri : nodeAttributes) {
+                        String[] nameURIPair = uri.trim().split(":");
+                        variable2URIAttributes.put(nameURIPair[0], nameURIPair[1]);
+                    }
+                } else if (comment.getText().startsWith(" BioMart XML-Query:")) {
+                    prelude = "<!--" + comment.getText() + "-->\n";
+                } else if (comment.getText().startsWith(" SPARQL-Exception:")) {
+                    exception = comment.getText().substring(18);
+                }
+            }
+        }
+
+        this.out = new org.biomart.processors.formatters.RDF(out,
+                variableNames,
+                variableProperties,
+                variableTypes,
+                variable2URIAttributes,
+                namespaces,
+                prelude,
+                exception,
+                org.biomart.processors.formatters.RDF.FORMAT.RDFXML);
+    }
+    
+    @Override
+    public void done() {
+        Closeables.closeQuietly(out);
+    }    
+}
