Change ATOM and RSS feed representations to use name value pairs instead of just strings, to allow support for all ATOM and RSS attributes and avoid confusion with non-feed string results.

git-svn-id: https://svn.apache.org/repos/asf/tuscany/sca-cpp/trunk@1079292 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/components/cache/client-test.cpp b/components/cache/client-test.cpp
index fce911a..bef5aa4 100644
--- a/components/cache/client-test.cpp
+++ b/components/cache/client-test.cpp
@@ -43,10 +43,13 @@
 bool testCache(const string& uri) {
     http::CURLSession cs("", "", "");
 
-    const list<value> i = list<value>()
+    const list<value> i = list<value>() + "content" + (list<value>() + "item" 
             + (list<value>() + "name" + string("Apple"))
-            + (list<value>() + "price" + string("$2.99"));
-    const list<value> a = mklist<value>(string("item"), string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b"), i);
+            + (list<value>() + "price" + string("$2.99")));
+    const list<value> a = list<value>() + (list<value>() + "entry" 
+            + (list<value>() + "title" + string("item"))
+            + (list<value>() + "id" + string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b"))
+            + i);
 
     const failable<value> id = http::post(a, uri, cs);
     assert(hasContent(id));
@@ -58,10 +61,13 @@
         assert(content(val) == a);
     }
 
-    const list<value> j = list<value>()
+    const list<value> j = list<value>() + "content" + (list<value>() + "item" 
             + (list<value>() + "name" + string("Apple"))
-            + (list<value>() + "price" + string("$3.55"));
-    const list<value> b = mklist<value>(string("item"), string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b"), j);
+            + (list<value>() + "price" + string("$3.55")));
+    const list<value> b = list<value>() + (list<value>() + "entry" 
+            + (list<value>() + "title" + string("item"))
+            + (list<value>() + "id" + string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b"))
+            + j);
 
     {
         const failable<value> r = http::put(b, uri + p, cs);
@@ -123,10 +129,13 @@
 };
 
 bool testGetPerf() {
-    const list<value> i = list<value>()
+    const list<value> i = list<value>() + "content" + (list<value>() + "item" 
             + (list<value>() + "name" + string("Apple"))
-            + (list<value>() + "price" + string("$4.55"));
-    const value a = mklist<value>(string("item"), string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b"), i);
+            + (list<value>() + "price" + string("$4.55")));
+    const list<value> a = list<value>() + (list<value>() + "entry" 
+            + (list<value>() + "title" + string("item"))
+            + (list<value>() + "id" + string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b"))
+            + i);
 
     http::CURLSession cs("", "", "");
     const failable<value> id = http::post(a, memcacheuri, cs);
diff --git a/components/chat/client-test.cpp b/components/chat/client-test.cpp
index 2c91fda..cd1021c 100644
--- a/components/chat/client-test.cpp
+++ b/components/chat/client-test.cpp
@@ -45,10 +45,13 @@
 const value jid3("sca3@localhost");
 const value pass3("sca3");
 
-const list<value> item = list<value>()
-        + (list<value>() + "name" + string("Apple"))
-        + (list<value>() + "price" + string("$2.99"));
-const list<value> entry = mklist<value>(string("item"), string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b"), item);
+const list<value> item = list<value>() + "content" + (list<value>() + "item" 
+    + (list<value>() + "name" + string("Apple"))
+    + (list<value>() + "price" + string("$2.99")));
+const list<value> entry = list<value>() + (list<value>() + "entry" 
+    + (list<value>() + "title" + string("item"))
+    + (list<value>() + "id" + string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b"))
+    + item);
 
 worker w(2);
 bool received;
diff --git a/components/filedb/client-test.cpp b/components/filedb/client-test.cpp
index a65ec45..97141eb 100644
--- a/components/filedb/client-test.cpp
+++ b/components/filedb/client-test.cpp
@@ -41,10 +41,13 @@
 bool testFileDB() {
     http::CURLSession cs("", "", "");
 
-    const list<value> i = list<value>()
+    const list<value> i = list<value>() + "content" + (list<value>() + "item" 
             + (list<value>() + "name" + string("Apple"))
-            + (list<value>() + "price" + string("$2.99"));
-    const list<value> a = mklist<value>(string("item"), string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b"), i);
+            + (list<value>() + "price" + string("$2.99")));
+    const list<value> a = list<value>() + (list<value>() + "entry" 
+            + (list<value>() + "title" + string("item"))
+            + (list<value>() + "id" + string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b"))
+            + i);
 
     const failable<value> id = http::post(a, uri, cs);
     assert(hasContent(id));
@@ -56,10 +59,13 @@
         assert(content(val) == a);
     }
 
-    const list<value> j = list<value>()
+    const list<value> j = list<value>() + "content" + (list<value>() + "item" 
             + (list<value>() + "name" + string("Apple"))
-            + (list<value>() + "price" + string("$3.55"));
-    const list<value> b = mklist<value>(string("item"), string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b"), j);
+            + (list<value>() + "price" + string("$3.55")));
+    const list<value> b = list<value>() + (list<value>() + "entry" 
+            + (list<value>() + "title" + string("item"))
+            + (list<value>() + "id" + string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b"))
+            + j);
 
     {
         const failable<value> r = http::put(b, uri + p, cs);
@@ -99,10 +105,13 @@
 };
 
 bool testGetPerf() {
-    const list<value> i = list<value>()
+    const list<value> i = list<value>() + "content" + (list<value>() + "item" 
             + (list<value>() + "name" + string("Apple"))
-            + (list<value>() + "price" + string("$4.55"));
-    const value a = mklist<value>(string("item"), string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b"), i);
+            + (list<value>() + "price" + string("$4.55")));
+    const list<value> a = list<value>() + (list<value>() + "entry" 
+            + (list<value>() + "title" + string("item"))
+            + (list<value>() + "id" + string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b"))
+            + i);
 
     http::CURLSession cs("", "", "");
     const failable<value> id = http::post(a, uri, cs);
diff --git a/components/log/client-test.cpp b/components/log/client-test.cpp
index 5f13f64..09651f4 100644
--- a/components/log/client-test.cpp
+++ b/components/log/client-test.cpp
@@ -41,10 +41,13 @@
 bool testLog() {
     http::CURLSession cs("", "", "");
 
-    const list<value> i = list<value>()
+    const list<value> i = list<value>() + "content" + (list<value>() + "item" 
             + (list<value>() + "name" + string("Apple"))
-            + (list<value>() + "price" + string("$2.99"));
-    const list<value> a = mklist<value>(string("item"), string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b"), i);
+            + (list<value>() + "price" + string("$2.99")));
+    const list<value> a = list<value>() + (list<value>() + "entry" 
+            + (list<value>() + "title" + string("item"))
+            + (list<value>() + "id" + string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b"))
+            + i);
 
     const failable<value> id = http::post(a, uri, cs);
     assert(hasContent(id));
@@ -66,10 +69,13 @@
 };
 
 bool testLogPerf() {
-    const list<value> i = list<value>()
+    const list<value> i = list<value>() + "content" + (list<value>() + "item" 
             + (list<value>() + "name" + string("Apple"))
-            + (list<value>() + "price" + string("$2.99"));
-    const value a = mklist<value>(string("item"), string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b"), i);
+            + (list<value>() + "price" + string("$2.99")));
+    const list<value> a = list<value>() + (list<value>() + "entry" 
+            + (list<value>() + "title" + string("item"))
+            + (list<value>() + "id" + string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b"))
+            + i);
 
     http::CURLSession cs("", "", "");
     const failable<value> id = http::post(a, uri, cs);
diff --git a/components/nosqldb/client-test.cpp b/components/nosqldb/client-test.cpp
index 8eed7ce..b64f838 100644
--- a/components/nosqldb/client-test.cpp
+++ b/components/nosqldb/client-test.cpp
@@ -41,10 +41,13 @@
 bool testNoSqlDb() {
     http::CURLSession cs("", "", "");
 
-    const list<value> i = list<value>()
+    const list<value> i = list<value>() + "content" + (list<value>() + "item" 
             + (list<value>() + "name" + string("Apple"))
-            + (list<value>() + "price" + string("$2.99"));
-    const list<value> a = mklist<value>(string("item"), string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b"), i);
+            + (list<value>() + "price" + string("$2.99")));
+    const list<value> a = list<value>() + (list<value>() + "entry" 
+            + (list<value>() + "title" + string("item"))
+            + (list<value>() + "id" + string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b"))
+            + i);
 
     const failable<value> id = http::post(a, uri, cs);
     assert(hasContent(id));
@@ -56,10 +59,13 @@
         assert(content(val) == a);
     }
 
-    const list<value> j = list<value>()
+    const list<value> j = list<value>() + "content" + (list<value>() + "item" 
             + (list<value>() + "name" + string("Apple"))
-            + (list<value>() + "price" + string("$3.55"));
-    const list<value> b = mklist<value>(string("item"), string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b"), j);
+            + (list<value>() + "price" + string("$3.55")));
+    const list<value> b = list<value>() + (list<value>() + "entry" 
+            + (list<value>() + "title" + string("item"))
+            + (list<value>() + "id" + string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b"))
+            + j);
 
     {
         const failable<value> r = http::put(b, uri + p, cs);
@@ -99,10 +105,13 @@
 };
 
 bool testGetPerf() {
-    const list<value> i = list<value>()
+    const list<value> i = list<value>() + "content" + (list<value>() + "item" 
             + (list<value>() + "name" + string("Apple"))
-            + (list<value>() + "price" + string("$4.55"));
-    const value a = mklist<value>(string("item"), string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b"), i);
+            + (list<value>() + "price" + string("$4.55")));
+    const list<value> a = list<value>() + (list<value>() + "entry" 
+            + (list<value>() + "title" + string("item"))
+            + (list<value>() + "id" + string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b"))
+            + i);
 
     http::CURLSession cs("", "", "");
     const failable<value> id = http::post(a, uri, cs);
diff --git a/components/queue/client-test.cpp b/components/queue/client-test.cpp
index 286faa2..d44fd0f 100644
--- a/components/queue/client-test.cpp
+++ b/components/queue/client-test.cpp
@@ -46,10 +46,13 @@
 const value key(mklist<value>(string("report")));
 const string qname("reportq");
 
-const list<value> item = list<value>()
-        + (list<value>() + "name" + string("Apple"))
-        + (list<value>() + "price" + string("$2.99"));
-const list<value> entry = mklist<value>(string("item"), string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b"), item);
+const list<value> item = list<value>() + "content" + (list<value>() + "item" 
+    + (list<value>() + "name" + string("Apple"))
+    + (list<value>() + "price" + string("$2.99")));
+const list<value> entry = list<value>() + (list<value>() + "entry" 
+    + (list<value>() + "title" + string("item"))
+    + (list<value>() + "id" + string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b"))
+    + item);
 
 bool testDeclareQueue() {
     QpidConnection qc;
diff --git a/components/sqldb/client-test.cpp b/components/sqldb/client-test.cpp
index 4e5c067..9e2cbdc 100644
--- a/components/sqldb/client-test.cpp
+++ b/components/sqldb/client-test.cpp
@@ -41,10 +41,13 @@
 bool testSqlDb() {
     http::CURLSession cs("", "", "");
 
-    const list<value> i = list<value>()
+    const list<value> i = list<value>() + "content" + (list<value>() + "item" 
             + (list<value>() + "name" + string("Apple"))
-            + (list<value>() + "price" + string("$2.99"));
-    const list<value> a = mklist<value>(string("item"), string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b"), i);
+            + (list<value>() + "price" + string("$2.99")));
+    const list<value> a = list<value>() + (list<value>() + "entry" 
+            + (list<value>() + "title" + string("item"))
+            + (list<value>() + "id" + string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b"))
+            + i);
 
     const failable<value> id = http::post(a, uri, cs);
     assert(hasContent(id));
@@ -56,10 +59,13 @@
         assert(content(val) == a);
     }
 
-    const list<value> j = list<value>()
+    const list<value> j = list<value>() + "content" + (list<value>() + "item" 
             + (list<value>() + "name" + string("Apple"))
-            + (list<value>() + "price" + string("$3.55"));
-    const list<value> b = mklist<value>(string("item"), string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b"), j);
+            + (list<value>() + "price" + string("$3.55")));
+    const list<value> b = list<value>() + (list<value>() + "entry" 
+            + (list<value>() + "title" + string("item"))
+            + (list<value>() + "id" + string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b"))
+            + j);
 
     {
         const failable<value> r = http::put(b, uri + p, cs);
@@ -99,10 +105,13 @@
 };
 
 bool testGetPerf() {
-    const list<value> i = list<value>()
+    const list<value> i = list<value>() + "content" + (list<value>() + "item" 
             + (list<value>() + "name" + string("Apple"))
-            + (list<value>() + "price" + string("$4.55"));
-    const value a = mklist<value>(string("item"), string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b"), i);
+            + (list<value>() + "price" + string("$4.55")));
+    const list<value> a = list<value>() + (list<value>() + "entry" 
+            + (list<value>() + "title" + string("item"))
+            + (list<value>() + "id" + string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b"))
+            + i);
 
     http::CURLSession cs("", "", "");
     const failable<value> id = http::post(a, uri, cs);
diff --git a/kernel/element.hpp b/kernel/element.hpp
index 1c44388..fb21aa6 100644
--- a/kernel/element.hpp
+++ b/kernel/element.hpp
@@ -95,7 +95,7 @@
 /**
  * Returns true if an element has a value.
  */
-const value elementHasValue(const list<value>& l) {
+const bool elementHasValue(const list<value>& l) {
     const list<value> r = reverse(l);
     if (isSymbol(car(r)))
         return false;
diff --git a/modules/atom/atom-test.cpp b/modules/atom/atom-test.cpp
index 5503c0f..3030777 100644
--- a/modules/atom/atom-test.cpp
+++ b/modules/atom/atom-test.cpp
@@ -93,19 +93,27 @@
         const list<value> i = list<value>() + element + value("item")
                 + value(list<value>() + element + value("name") + value(string("Apple")))
                 + value(list<value>() + element + value("price") + value(string("$2.99")));
-        const list<value> a = mklist<value>(string("item"), string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b"), i);
+        const list<value> a = list<value>() + (list<value>() + element + value("entry")
+                + value(list<value>() + element + value("title") + value(string("item")))
+                + value(list<value>() + element + value("id") + value(string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b")))
+                + value(list<value>() + element + value("content") + value(i)));
         ostringstream os;
         writeATOMEntry<ostream*>(writer, &os, a);
         assert(str(os) == itemEntry);
     }
     {
-        const list<value> a = mklist<value>(string("item"), string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b"), string("Apple"));
+        const list<value> a = list<value>() + (list<value>() + element + value("entry")
+                + value(list<value>() + element + value("title") + value(string("item")))
+                + value(list<value>() + element + value("id") + value(string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b")))
+                + value(list<value>() + element + value("content") + value(string("Apple"))));
         ostringstream os;
         writeATOMEntry<ostream*>(writer, &os, a);
         assert(str(os) == itemTextEntry);
     }
     {
-        const list<value> a = mklist<value>(string("item"), string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b"), list<value>());
+        const list<value> a = list<value>() + (list<value>() + element + value("entry")
+                + value(list<value>() + element + value("title") + value(string("item")))
+                + value(list<value>() + element + value("id") + value(string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b"))));
         ostringstream os;
         writeATOMEntry<ostream*>(writer, &os, a);
         assert(str(os) == itemNoContentEntry);
@@ -173,8 +181,11 @@
 
 bool testFeed() {
     {
+        const list<value> a = list<value>() + (list<value>() + element + value("feed")
+                + value(list<value>() + element + value("title") + value(string("Feed")))
+                + value(list<value>() + element + value("id") + value(string("1234"))));
         ostringstream os;
-        writeATOMFeed<ostream*>(writer, &os, mklist<value>("Feed", "1234"));
+        writeATOMFeed<ostream*>(writer, &os, a);
         assert(str(os) == emptyFeed);
     }
     {
@@ -184,31 +195,29 @@
         assert(str(os) == emptyFeed);
     }
     {
-        const list<value> i = list<value>()
-                + (list<value>() + "item" + "cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b"
-                    + (list<value>() + element + "item"
+        const list<value> i1 = list<value>() + element + "item"
                         + (list<value>() + element + "name" + "Apple")
-                        + (list<value>() + element + "price" + "$2.99")))
-                + (list<value>() + "item" + "cart-53d67a61-aa5e-4e5e-8401-39edeba8b83c"
-                    + (list<value>() + element + "item"
+                        + (list<value>() + element + "price" + "$2.99");
+
+        const list<value> i2 = list<value>() + element + "item"
                         + (list<value>() + element + "name" + "Orange")
-                        + (list<value>() + element + "price" + "$3.55")));
-        const list<value> a = cons<value>("Feed", cons<value>("1234", i));
-        ostringstream os;
-        writeATOMFeed<ostream*>(writer, &os, a);
-        assert(str(os) == itemFeed);
-    }
-    {
+                        + (list<value>() + element + "price" + "$3.55");
+
         const list<value> i = list<value>()
-                + (list<value>() + "item" + "cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b"
-                    + valueToElement(list<value>() + "item"
-                        + (list<value>() + "name" + "Apple")
-                        + (list<value>() + "price" + "$2.99")))
-                + (list<value>() + "item" + "cart-53d67a61-aa5e-4e5e-8401-39edeba8b83c"
-                    + valueToElement(list<value>() + "item"
-                        + (list<value>() + "name" + "Orange")
-                        + (list<value>() + "price" + "$3.55")));
-        const list<value> a = cons<value>("Feed", cons<value>("1234", i));
+            + value(list<value>() + element + value("entry")
+                + value(list<value>() + element + value("title") + value(string("item")))
+                + value(list<value>() + element + value("id") + value(string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b")))
+                + value(list<value>() + element + value("content") + value(i1)))
+            + value(list<value>() + element + value("entry")
+                + value(list<value>() + element + value("title") + value(string("item")))
+                + value(list<value>() + element + value("id") + value(string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83c")))
+                + value(list<value>() + element + value("content") + value(i2)));
+        
+        const list<value> a = list<value>() + (append<value>(list<value>() + element + value("feed")
+                + value(list<value>() + element + value("title") + value(string("Feed")))
+                + value(list<value>() + element + value("id") + value("1234")),
+                i));
+
         ostringstream os;
         writeATOMFeed<ostream*>(writer, &os, a);
         assert(str(os) == itemFeed);
@@ -219,6 +228,12 @@
         writeATOMFeed<ostream*>(writer, &os, a);
         assert(str(os) == itemFeed);
     }
+    {
+        const list<value> a = elementsToValues(content(readATOMFeed(mklist(itemFeed))));
+        ostringstream os;
+        writeATOMFeed<ostream*>(writer, &os, valuesToElements(a));
+        assert(str(os) == itemFeed);
+    }
     return true;
 }
 
diff --git a/modules/atom/atom.hpp b/modules/atom/atom.hpp
index 0201995..1d4a12a 100644
--- a/modules/atom/atom.hpp
+++ b/modules/atom/atom.hpp
@@ -36,24 +36,33 @@
 namespace atom {
 
 /**
- * Convert a list of elements to a list of values representing an ATOM entry.
+ * Tags used to tag feed and entry elements.
  */
-const list<value> entryElementsToValues(const list<value>& e) {
+const value feed("feed");
+const value entry("entry");
+
+/**
+ * Convert a list of elements to a list of element values representing an ATOM entry.
+ */
+const list<value> entryElementValues(const list<value>& e) {
     const list<value> lt = filter<value>(selector(mklist<value>(element, "title")), e);
     const value t = isNil(lt)? value(emptyString) : elementValue(car(lt));
     const list<value> li = filter<value>(selector(mklist<value>(element, "id")), e);
     const value i = isNil(li)? value(emptyString) : elementValue(car(li));
     const list<value> lc = filter<value>(selector(mklist<value>(element, "content")), e);
-    return mklist<value>(t, i, isNil(lc)? (value)list<value>() : elementValue(car(lc)));
+    return append<value>(list<value>() + element + entry 
+                + value(list<value>() + element + value("title") + t)
+                + value(list<value>() + element + value("id") + i),
+                isNil(lc)? list<value>() : mklist<value>(value(list<value>() + element + value("content") + elementValue(car(lc)))));
 }
 
 /**
- * Convert a list of elements to a list of values representing ATOM entries.
+ * Convert a list of elements to a list of element values representing ATOM entries.
  */
-const list<value> entriesElementsToValues(const list<value>& e) {
+const list<value> entriesElementValues(const list<value>& e) {
     if (isNil(e))
         return e;
-    return cons<value>(entryElementsToValues(car(e)), entriesElementsToValues(cdr(e)));
+    return cons<value>(entryElementValues(car(e)), entriesElementValues(cdr(e)));
 }
 
 /**
@@ -81,15 +90,7 @@
     const list<value> e = readXML(ilist);
     if (isNil(e))
         return mkfailure<list<value> >("Empty entry");
-    return entryElementsToValues(car(e));
-}
-
-/**
- * Convert a list of values representing an ATOM entry to a value.
- */
-const value entryValue(const list<value>& e) {
-    const list<value> v = elementsToValues(mklist<value>(caddr(e)));
-    return cons(car(e), mklist<value>(cadr(e), isList(car(v))? (isNil((list<value>)car(v))? car(v) : (value)cdr<value>(car(v))) : car(v)));
+    return mklist<value>(entryElementValues(car(e)));
 }
 
 /**
@@ -101,42 +102,34 @@
         return mkfailure<list<value> >("Empty feed");
     const list<value> t = filter<value>(selector(mklist<value>(element, "title")), car(f));
     const list<value> i = filter<value>(selector(mklist<value>(element, "id")), car(f));
-    const list<value> e = filter<value>(selector(mklist<value>(element, "entry")), car(f));
-    if (isNil(e))
-        return mklist<value>(elementValue(car(t)), elementValue(car(i)));
-    return cons<value>(elementValue(car(t)), cons(elementValue(car(i)), entriesElementsToValues(e)));
+    const list<value> e = filter<value>(selector(mklist<value>(element, entry)), car(f));
+    return mklist<value>(append<value>(list<value>() + element + feed 
+                + value(list<value>() + element + value("title") + elementValue(car(t)))
+                + value(list<value>() + element + value("id") + elementValue(car(i))),
+                entriesElementValues(e)));
 }
 
 /**
- * Convert an ATOM feed containing elements to an ATOM feed containing values.
- */
-const list<value> feedValuesLoop(const list<value> e) {
-    if (isNil(e))
-        return e;
-    return cons<value>(entryValue(car(e)), feedValuesLoop(cdr(e)));
-}
-
-const list<value> feedValues(const list<value>& e) {
-    return cons(car<value>(e), cons<value>(cadr<value>(e), feedValuesLoop(cddr<value>(e))));
-}
-
-/**
- * Convert a list of values representing an ATOM entry to a list of elements.
- * The first two values in the list are the entry title and id.
+ * Convert a list of element values representing an ATOM entry to a list of elements.
  */
 const list<value> entryElement(const list<value>& l) {
+    const value title = elementValue(elementChild("title", l));
+    const value id = elementValue(elementChild("id", l));
+    const value content = elementChild("content", l);
+    const bool text = isNil(content)? false : elementHasValue(content);
     return list<value>()
-        + element + "entry" + (list<value>() + attribute + "xmlns" + "http://www.w3.org/2005/Atom")
-        + (list<value>() + element + "title" + (list<value>() + attribute + "type" + "text") + car(l))
-        + (list<value>() + element + "id" + cadr(l))
-        + (isNil(cddr(l))?
+        + element + entry + (list<value>() + attribute + "xmlns" + "http://www.w3.org/2005/Atom")
+        + (list<value>() + element + "title" + (list<value>() + attribute + "type" + "text") + title)
+        + (list<value>() + element + "id" + id)
+        + (isNil(content)?
             list<value>() :
-            list<value>() + element + "content" + (list<value>() + attribute + "type" + (isList(caddr(l))? "application/xml" : "text")) + caddr(l))
-        + (list<value>() + element + "link" + (list<value>() + attribute + "href" + cadr(l)));
+            append<value>(list<value>() + element + "content" + (list<value>() + attribute + "type" + (text? "text" : "application/xml")),
+                text? mklist<value>(elementValue(content)) : elementChildren(content)))
+        + (list<value>() + element + "link" + (list<value>() + attribute + "href" + id));
 }
 
 /**
- * Convert a list of values representing ATOM entries to a list of elements.
+ * Convert a list of element values representing ATOM entries to a list of elements.
  */
 const list<value> entriesElements(const list<value>& l) {
     if (isNil(l))
@@ -145,10 +138,10 @@
 }
 
 /**
- * Convert a list of values representing an ATOM entry to an ATOM entry.
- * The first two values in the list are the entry id and title.
+ * Convert a list of element values representing an ATOM entry to an ATOM entry.
  */
-template<typename R> const failable<R> writeATOMEntry(const lambda<R(const string&, const R)>& reduce, const R& initial, const list<value>& l) {
+template<typename R> const failable<R> writeATOMEntry(const lambda<R(const string&, const R)>& reduce, const R& initial, const list<value>& ll) {
+    const list<value> l = isNil(ll)? ll : (list<value>)car(ll);
     return writeXML<R>(reduce, initial, mklist<value>(entryElement(l)));
 }
 
@@ -160,23 +153,37 @@
 }
 
 /**
- * Convert a list of values representing an ATOM feed to an ATOM feed.
- * The first two values in the list are the feed id and title.
+ * Convert a list of element values representing an ATOM feed to an ATOM feed.
  */
-template<typename R> const failable<R> writeATOMFeed(const lambda<R(const string&, const R)>& reduce, const R& initial, const list<value>& l) {
+template<typename R> const failable<R> writeATOMFeed(const lambda<R(const string&, const R)>& reduce, const R& initial, const list<value>& ll) {
+    const list<value> l = isNil(ll)? ll : (list<value>)car(ll);
+    const list<value> lt = filter<value>(selector(mklist<value>(element, "title")), l);
+    const value t = isNil(lt)? value(emptyString) : elementValue(car(lt));
+    const list<value> li = filter<value>(selector(mklist<value>(element, "id")), l);
+    const value i = isNil(li)? value(emptyString) : elementValue(car(li));
     const list<value> f = list<value>()
-        + element + "feed" + (list<value>() + attribute + "xmlns" + "http://www.w3.org/2005/Atom")
-        + (list<value>() + element + "title" + (list<value>() + attribute + "type" + "text") + car(l))
-        + (list<value>() + element + "id" + cadr(l));
-    if (isNil(cddr(l)))
+        + element + feed + (list<value>() + attribute + "xmlns" + "http://www.w3.org/2005/Atom")
+        + (list<value>() + element + "title" + (list<value>() + attribute + "type" + "text") + t)
+        + (list<value>() + element + "id" + i);
+
+    // Write ATOM entries
+    const list<value> le = filter<value>(selector(mklist<value>(element, entry)), l);
+    if (isNil(le))
         return writeXML<R>(reduce, initial, mklist<value>(f));
-    const list<value> fe = append(f, entriesElements(cddr(l)));
+
+    // Write a single ATOM entry element with a list of values
+    if (!isNil(le) && !isNil(car(le)) && isList(car<value>(caddr<value>(car(le))))) {
+        const list<value> fe = append(f, entriesElements(caddr<value>(car(le))));
+        return writeXML<R>(reduce, initial, mklist<value>(fe));
+    }
+
+    // Write separate ATOM entry elements
+    const list<value> fe = append(f, entriesElements(le));
     return writeXML<R>(reduce, initial, mklist<value>(fe));
 }
 
 /**
- * Convert a list of values representing an ATOM feed to a list of strings.
- * The first two values in the list are the feed id and title.
+ * Convert a list of element values representing an ATOM feed to a list of strings.
  */
 const failable<list<string> > writeATOMFeed(const list<value>& l) {
     const failable<list<string> > ls = writeATOMFeed<list<string>>(rcons<string>, list<string>(), l);
@@ -185,28 +192,6 @@
     return reverse(list<string>(content(ls)));
 }
 
-/**
- * Convert an ATOM entry containing a value to an ATOM entry containing an item element.
- */
-const list<value> entryValuesToElements(const list<value> val) {
-    if (isList(caddr(val)))
-        return cons(car(val), cons(cadr(val), valuesToElements(mklist<value>(cons<value>("item", (list<value>)caddr(val))))));
-    return cons(car(val), cons(cadr(val), valuesToElements(mklist<value>(mklist<value>("item", caddr(val))))));
-}
-
-/**
- * Convert an ATOM feed containing values to an ATOM feed containing elements.
- */
-const list<value> feedValuesToElementsLoop(const list<value> val) {
-    if (isNil(val))
-        return val;
-    return cons<value>(entryValuesToElements(car(val)), feedValuesToElementsLoop(cdr(val)));
-}
-
-const list<value> feedValuesToElements(const list<value>& val) {
-    return cons(car<value>(val), cons<value>(cadr<value>(val), feedValuesToElementsLoop(cddr<value>(val))));
-}
-
 }
 }
 
diff --git a/modules/edit/apps.py b/modules/edit/apps.py
index d0a54ac..2980a9e 100644
--- a/modules/edit/apps.py
+++ b/modules/edit/apps.py
@@ -39,14 +39,14 @@
 # Post a new app to the apps db
 def post(collection, app, cache):
     id = appid((str(uuid.uuid1()),))
-    comp = caddr(app)
+    comp = cdr(cadddr(car(app)))
     cache.put((id,), comp)
     mkapplink((id,))
     return id
 
 # Put an app into the apps db
 def put(id, app, cache):
-    comp = caddr(app)
+    comp = cdr(cadddr(car(app)))
     cache.put(appid(id), comp)
     mkapplink(id)
     return True
@@ -54,8 +54,11 @@
 # Get an app from the apps db
 def get(id, cache):
     if isNil(id):
-        return ("Apps", "apps")
-    return (car(id), car(id), cache.get(appid(id)))
+        return (("'feed", ("'title", "Apps"), ("'id", "apps")),)
+    app = cache.get(appid(id));
+    if (isNil(app) or app is None):
+        return (("'entry", ("'title", car(id)), ("'id", car(id))),)
+    return (("'entry", ("'title", car(id)), ("'id", car(id)), ("'content", car(app))),)
 
 # Delete an app from the apps db
 def delete(id, cache):
diff --git a/modules/edit/apps/myprofile/app.composite b/modules/edit/apps/me360/app.composite
similarity index 100%
rename from modules/edit/apps/myprofile/app.composite
rename to modules/edit/apps/me360/app.composite
diff --git a/modules/edit/apps/myprofile/app.html b/modules/edit/apps/me360/app.html
similarity index 100%
rename from modules/edit/apps/myprofile/app.html
rename to modules/edit/apps/me360/app.html
diff --git a/modules/edit/apps/myprofile2/app.composite b/modules/edit/apps/myprofile2/app.composite
deleted file mode 100644
index 86a6ce6..0000000
--- a/modules/edit/apps/myprofile2/app.composite
+++ /dev/null
@@ -1,118 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- * 
- *   http://www.apache.org/licenses/LICENSE-2.0
- * 
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.    
--->
-<composite xmlns="http://docs.oasis-open.org/ns/opencsa/sca/200912" xmlns:t="http://tuscany.apache.org/xmlns/sca/1.1" targetNamespace="http://myprofile2" name="myprofile2">
- <service name="opened" promote="opened"/>
- <component t:x="0" t:y="13" name="opened" t:title="when page opened" t:color="green1">
-  <t:implementation.python script="opened.py"/>
-  <service name="opened" t:visible="false"/>
-  <reference target="nothing" name="content"/>
- </component>
- <component t:x="133" t:y="11" name="nothing" t:color="orange1">
-  <t:implementation.python script="text.py"/>
-  <service name="nothing"/>
- </component>
- <service name="getProfiles" promote="getProfiles"/>
- <component name="getProfiles" t:x="0" t:y="99" t:title="when clicked" t:color="green1">
-  <t:implementation.python script="clicked.py"/>
-  <service name="clicked" t:visible="false"/>
-  <property>getProfiles</property>
-  <reference target="list5" name="content"/>
- </component>
- <component t:x="98" t:y="100" name="list5" t:title="make list" t:color="yellow1">
-  <t:implementation.python script="list_.py"/>
-  <service name="list"/>
-  <reference target="assoc" name="first"/>
-  <reference target="list6" name="rest"/>
- </component>
- <component t:x="223" t:y="140" name="fbprofile2" t:title="facebook profile" t:color="blue1">
-  <t:implementation.python script="fbprofile.py"/>
-  <service name="fbprofile"/>
-  <reference target="find3" name="id"/>
- </component>
- <component t:x="176" t:y="144" name="list6" t:title="make list" t:color="yellow1">
-  <t:implementation.python script="list_.py"/>
-  <service name="list"/>
-  <reference target="assoc2" name="first"/>
-  <reference target="empty" name="rest"/>
- </component>
- <component t:x="176" t:y="99" name="assoc" t:title="assoc" t:color="orange1">
-  <t:implementation.python script="assoc.py"/>
-  <service name="assoc"/>
-  <reference target="name" name="name"/>
-  <reference target="fbprofile2" name="value"/>
- </component>
- <component t:x="299" t:y="269" name="twprofile2" t:title="twitter profile" t:color="blue1">
-  <t:implementation.python script="twprofile.py"/>
-  <service name="twprofile"/>
-  <reference target="find4" name="id"/>
- </component>
- <component t:x="337" t:y="142" name="find3" t:title="find by name" t:color="yellow1">
-  <t:implementation.python script="find.py"/>
-  <service name="find"/>
-  <reference target="name4" name="name"/>
-  <reference target="params3" name="assoc"/>
- </component>
- <component t:x="439" t:y="140" name="name4" t:title="name" t:color="orange1">
-  <t:implementation.python script="name.py"/>
-  <service name="name"/>
-  <property>fbid</property>
- </component>
- <component t:x="399" t:y="344" name="find4" t:title="find by name" t:color="yellow1">
-  <t:implementation.python script="find.py"/>
-  <service name="find"/>
-  <reference target="name5" name="name"/>
-  <reference target="params4" name="assoc"/>
- </component>
- <component t:x="495" t:y="345" name="name5" t:title="name" t:color="orange1">
-  <t:implementation.python script="name.py"/>
-  <service name="name"/>
-  <property>twid</property>
- </component>
- <component t:x="221" t:y="99" name="name" t:title="name" t:color="orange1">
-  <t:implementation.python script="name.py"/>
-  <service name="name"/>
-  <property>fbprofile</property>
- </component>
- <component t:x="256" t:y="262" name="assoc2" t:title="assoc" t:color="orange1">
-  <t:implementation.python script="assoc.py"/>
-  <service name="assoc"/>
-  <reference target="name3" name="name"/>
-  <reference target="twprofile2" name="value"/>
- </component>
- <component t:x="256" t:y="424" name="empty" t:title="empty list" t:color="yellow1">
-  <t:implementation.python script="empty.py"/>
-  <service name="empty"/>
- </component>
- <component t:x="298" t:y="261" name="name3" t:title="name" t:color="orange1">
-  <t:implementation.python script="name.py"/>
-  <service name="name"/>
-  <property>twprofile</property>
- </component>
- <component t:x="436" t:y="183" name="params3" t:title="?params" t:color="green1">
-  <t:implementation.python script="params.py"/>
-  <service name="params"/>
-  <property>fbid=1234567&amp;twid=joe</property>
- </component>
- <component t:x="495" t:y="345" name="params4" t:title="?params" t:color="green1">
-  <t:implementation.python script="params.py"/>
-  <service name="params"/>
-  <property>fbid=1234567&amp;twid=joe</property>
- </component>
-</composite>
diff --git a/modules/edit/apps/myprofile2/app.html b/modules/edit/apps/myprofile2/app.html
deleted file mode 100644
index b09564d..0000000
--- a/modules/edit/apps/myprofile2/app.html
+++ /dev/null
@@ -1,45 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- * 
- *   http://www.apache.org/licenses/LICENSE-2.0
- * 
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.    
--->
-<DIV id="page">
- <SPAN id="h1" class="h1" style="position: absolute; top: 6px; left: 0px; ">
-  <H1>My social profiles</H1>
- </SPAN>
- <SPAN id="getProfiles" class="button" style="position: absolute; top: 144px; left: 0px; ">
-  <INPUT type="button" value="Get my profiles"/>
- </SPAN>
- <SPAN id="h2" class="h2" style="position: absolute; top: 198px; left: 0px; ">
-  <H2>Facebook profile</H2>
- </SPAN>
- <SPAN id="fbprofile" class="text" style="position: absolute; top: 240px; left: 3px; ">
-  <SPAN>text</SPAN>
- </SPAN>
- <SPAN id="h2" class="h2" style="position: absolute; top: 283px; left: 1px; ">
-  <H2>Twitter profile</H2>
- </SPAN>
- <SPAN id="twprofile" class="text" style="position: absolute; top: 331px; left: 2px; ">
-  <SPAN>text</SPAN>
- </SPAN>
- <SPAN id="twid" class="entry" style="position: absolute; top: 99px; left: 0px; ">
-  <INPUT type="text" value="field" size="5"/>
- </SPAN>
- <SPAN id="fbid" class="entry" style="position: absolute; top: 56px; left: 0px; ">
-  <INPUT type="text" value="field" size="5"/>
- </SPAN>
-</DIV>
diff --git a/modules/edit/apps/nearme2/app.composite b/modules/edit/apps/nearme2/app.composite
deleted file mode 100644
index 11c9671..0000000
--- a/modules/edit/apps/nearme2/app.composite
+++ /dev/null
@@ -1,123 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- * 
- *   http://www.apache.org/licenses/LICENSE-2.0
- * 
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.    
--->
-<composite xmlns="http://docs.oasis-open.org/ns/opencsa/sca/200912" xmlns:t="http://tuscany.apache.org/xmlns/sca/1.1" targetNamespace="http://nearme2" name="nearme2">
- <service name="every" promote="every"/>
- <component t:x="0" t:y="25" name="every" t:title="every n secs" t:color="green1">
-  <t:implementation.python script="every.py"/>
-  <service name="every" t:visible="false"/>
-  <property>60</property>
-  <reference target="gtalksend" name="content"/>
- </component>
- <component t:x="100" t:y="25" name="gtalksend" t:title="send gtalk" t:color="blue1">
-  <t:implementation.python script="gtalksend.py"/>
-  <service name="gtalksend"/>
-  <reference target="filter" name="jid"/>
-  <reference target="user" name="to"/>
-  <reference target="text" name="msg"/>
- </component>
- <component t:x="184" t:y="54" name="user" t:title="user" t:color="green1">
-  <t:implementation.python script="user.py"/>
-  <service name="user"/>
-  <property name="user"/>
- </component>
- <component t:x="183" t:y="97" name="text" t:title="text" t:color="orange1">
-  <t:implementation.python script="text.py"/>
-  <service name="text"/>
-  <property>Hey I'm here!</property>
- </component>
- <component t:x="184" t:y="24" name="filter" t:title="filter" t:color="yellow1">
-  <t:implementation.python script="filter_.py"/>
-  <service name="filter"/>
-  <reference target="fbfriend" name="item"/>
-  <reference target="lesser" name="condition"/>
-  <reference target="fbfriends" name="list"/>
- </component>
- <component t:x="234" t:y="25" name="fbfriend" t:color="yellow1">
-  <t:implementation.python script="item.py"/>
-  <service name="item"/>
-  <property name="property"/>
- </component>
- <component t:x="233" t:y="97" name="fbfriends" t:title="facebook friends" t:color="blue1">
-  <t:implementation.python script="fbfriends.py"/>
-  <service name="fbfriends"/>
-  <reference target="find" name="id"/>
- </component>
- <component t:x="352" t:y="96" name="find" t:title="find by name" t:color="yellow1">
-  <t:implementation.python script="find.py"/>
-  <service name="find"/>
-  <reference target="name" name="name"/>
-  <reference target="params" name="assoc"/>
- </component>
- <component t:x="453" t:y="97" name="name" t:title="name" t:color="orange1">
-  <t:implementation.python script="name.py"/>
-  <service name="name"/>
-  <property>fbid</property>
- </component>
- <component t:x="453" t:y="138" name="params" t:title="?params" t:color="green1">
-  <t:implementation.python script="params.py"/>
-  <service name="params"/>
-  <property>fbid=1234567</property>
- </component>
- <component t:x="235" t:y="67" name="lesser" t:title="lt" t:color="magenta1">
-  <t:implementation.python script="lesser.py"/>
-  <service name="lesser"/>
-  <reference target="subtract" name="value1"/>
-  <reference target="mile" name="value2"/>
- </component>
- <component t:x="274" t:y="97" name="mile" t:title="number" t:color="orange1">
-  <t:implementation.python script="number.py"/>
-  <service name="number"/>
-  <property>1</property>
- </component>
- <component t:x="274" t:y="67" name="subtract" t:title="-" t:color="magenta1">
-  <t:implementation.python script="subtract.py"/>
-  <service name="subtract">
-   <documentation>-</documentation>
-  </service>
-  <reference target="location" name="value1"/>
-  <reference target="location2" name="value2"/>
- </component>
- <component t:x="316" t:y="68" name="location" t:title="location" t:color="red1">
-  <t:implementation.python script="location.py"/>
-  <service name="location"/>
-  <reference target="find2" name="user"/>
- </component>
- <component t:x="316" t:y="122" name="location2" t:title="location" t:color="red1">
-  <t:implementation.python script="location.py"/>
-  <service name="location"/>
-  <reference target="user2" name="user"/>
- </component>
- <component t:x="386" t:y="118" name="user2" t:title="user" t:color="green1">
-  <t:implementation.python script="user.py"/>
-  <service name="user"/>
-  <property name="user"/>
- </component>
- <component t:x="386" t:y="69" name="find2" t:title="find by name" t:color="yellow1">
-  <t:implementation.python script="find.py"/>
-  <service name="find"/>
-  <reference target="name2" name="name"/>
-  <reference target="fbfriend" name="assoc"/>
- </component>
- <component t:x="484" t:y="68" name="name2" t:title="name" t:color="orange1">
-  <t:implementation.python script="name.py"/>
-  <service name="name"/>
-  <property>id</property>
- </component>
-</composite>
diff --git a/modules/edit/apps/nearme2/app.html b/modules/edit/apps/nearme2/app.html
deleted file mode 100644
index 5c7c721..0000000
--- a/modules/edit/apps/nearme2/app.html
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- * 
- *   http://www.apache.org/licenses/LICENSE-2.0
- * 
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.    
--->
-<DIV id="page"/>
diff --git a/modules/edit/apps/store/app.composite b/modules/edit/apps/store/app.composite
deleted file mode 100644
index 0c676c1..0000000
--- a/modules/edit/apps/store/app.composite
+++ /dev/null
@@ -1,60 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- * 
- *   http://www.apache.org/licenses/LICENSE-2.0
- * 
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.    
--->
-<composite xmlns="http://docs.oasis-open.org/ns/opencsa/sca/200912" xmlns:t="http://tuscany.apache.org/xmlns/sca/1.1" targetNamespace="http://store" name="store">
- <service name="Store" promote="Store"/>
- <service name="ShoppingCart" promote="ShoppingCart"/>
- <component name="Store" t:color="green1">
-  <t:implementation.python script="store.py"/>
-  <service name="Widget">
-   <t:binding.http uri="store"/>
-  </service>
-  <reference name="catalog" target="Catalog"/>
-  <reference name="shoppingCart" target="ShoppingCart"/>
-  <reference name="shoppingTotal" target="ShoppingCart"/>
- </component>
- <component name="Catalog" t:color="yellow1">
-  <t:implementation.python script="fruits-catalog.py"/>
-  <property>USD</property>
-  <service name="Catalog">
-   <t:binding.jsonrpc uri="catalog"/>
-  </service>
-  <reference name="currencyConverter" target="CurrencyConverter"/>
- </component>
- <component name="ShoppingCart" t:color="magenta1">
-  <t:implementation.python script="shopping-cart.py"/>
-  <service name="ShoppingCart">
-   <t:binding.http uri="shoppingCart"/>
-  </service>
-  <reference name="cache" target="Cache"/>
- </component>
- <component name="CurrencyConverter" t:color="blue1">
-  <t:implementation.python script="currency-converter.py"/>
-  <service name="CurrencyConverter">
-   <t:binding.jsonrpc uri="currencyConverter"/>
-  </service>
- </component>
- <component name="Cache" t:color="orange1">
-  <implementation.cpp path="../../components/cache" library="libmemcache"/>
-  <service name="Cache">
-   <t:binding.atom uri="cache"/>
-  </service>
-  <property>localhost:11211</property>
- </component>
-</composite>
diff --git a/modules/edit/apps/store/app.html b/modules/edit/apps/store/app.html
deleted file mode 100644
index 593d0a6..0000000
--- a/modules/edit/apps/store/app.html
+++ /dev/null
@@ -1,47 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- * 
- *   http://www.apache.org/licenses/LICENSE-2.0
- * 
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.    
--->
-<DIV id="page">
- <SPAN id="storeh1" class="h1" style="position: absolute; top: 0px; left: 0px; ">
-  <H1>Store</H1>
- </SPAN>
- <SPAN id="catalogh2" class="h2" style="position: absolute; top: 40px; left: 0px; ">
-  <H2>Catalog</H2>
- </SPAN>
- <SPAN id="addToCart" class="button" style="position: absolute; top: 160px; left: 0px; ">
-  <INPUT type="button" value="Add to Cart"/>
- </SPAN>
- <SPAN id="carth2" class="h2" style="position: absolute; top: 200px; left: 0px; ">
-  <H2>Your Shopping Cart</H2>
- </SPAN>
- <SPAN id="total" class="text" style="position: absolute; top: 300px; left: 0px; ">
-  <SPAN>total</SPAN>
- </SPAN>
- <SPAN id="checkout" class="button" style="position: absolute; top: 340px; left: 0px; ">
-  <INPUT type="button" value="Checkout"/>
- </SPAN>
- <SPAN id="empty" class="button" style="position: absolute; top: 340px; left: 120px; ">
-  <INPUT type="button" value="Empty"/>
- </SPAN>
- <SPAN id="feed" class="link" style="position: absolute; top: 340px; left: 240px; ">
-  <A href="shoppingCart/">
-   <SPAN>(feed)</SPAN>
-  </A>
- </SPAN>
-</DIV>
diff --git a/modules/edit/apps/store2/app.composite b/modules/edit/apps/store2/app.composite
deleted file mode 100644
index b75877c..0000000
--- a/modules/edit/apps/store2/app.composite
+++ /dev/null
@@ -1,60 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- * 
- *   http://www.apache.org/licenses/LICENSE-2.0
- * 
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.    
--->
-<composite xmlns="http://docs.oasis-open.org/ns/opencsa/sca/200912" xmlns:t="http://tuscany.apache.org/xmlns/sca/1.1" targetNamespace="http://store" name="store">
- <service name="Store" promote="Store"/>
- <service name="ShoppingCart" promote="ShoppingCart"/>
- <component name="Store" t:color="green1">
-  <t:implementation.python script="store.py"/>
-  <service name="Widget">
-   <t:binding.http uri="store"/>
-  </service>
-  <reference name="catalog" target="Catalog" t:align="bottom"/>
-  <reference name="shoppingCart" target="ShoppingCart"/>
-  <reference name="shoppingTotal" target="ShoppingCart"/>
- </component>
- <component name="Catalog" t:color="yellow1">
-  <t:implementation.python script="fruits-catalog.py"/>
-  <property>USD</property>
-  <service name="Catalog" t:align="top">
-   <t:binding.jsonrpc uri="catalog"/>
-  </service>
-  <reference name="currencyConverter" t:align="bottom" target="CurrencyConverter"/>
- </component>
- <component name="ShoppingCart" t:color="magenta1">
-  <t:implementation.python script="shopping-cart.py"/>
-  <service name="ShoppingCart">
-   <t:binding.http uri="shoppingCart"/>
-  </service>
-  <reference name="cache" target="Cache"/>
- </component>
- <component name="CurrencyConverter" t:color="blue1">
-  <t:implementation.python script="currency-converter.py"/>
-  <service name="CurrencyConverter" t:align="top">
-   <t:binding.jsonrpc uri="currencyConverter"/>
-  </service>
- </component>
- <component name="Cache" t:color="orange1">
-  <implementation.cpp path="../../components/cache" library="libmemcache"/>
-  <service name="Cache">
-   <t:binding.atom uri="cache"/>
-  </service>
-  <property>localhost:11211</property>
- </component>
-</composite>
diff --git a/modules/edit/apps/store2/app.html b/modules/edit/apps/store2/app.html
deleted file mode 100644
index 593d0a6..0000000
--- a/modules/edit/apps/store2/app.html
+++ /dev/null
@@ -1,47 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- * 
- *   http://www.apache.org/licenses/LICENSE-2.0
- * 
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.    
--->
-<DIV id="page">
- <SPAN id="storeh1" class="h1" style="position: absolute; top: 0px; left: 0px; ">
-  <H1>Store</H1>
- </SPAN>
- <SPAN id="catalogh2" class="h2" style="position: absolute; top: 40px; left: 0px; ">
-  <H2>Catalog</H2>
- </SPAN>
- <SPAN id="addToCart" class="button" style="position: absolute; top: 160px; left: 0px; ">
-  <INPUT type="button" value="Add to Cart"/>
- </SPAN>
- <SPAN id="carth2" class="h2" style="position: absolute; top: 200px; left: 0px; ">
-  <H2>Your Shopping Cart</H2>
- </SPAN>
- <SPAN id="total" class="text" style="position: absolute; top: 300px; left: 0px; ">
-  <SPAN>total</SPAN>
- </SPAN>
- <SPAN id="checkout" class="button" style="position: absolute; top: 340px; left: 0px; ">
-  <INPUT type="button" value="Checkout"/>
- </SPAN>
- <SPAN id="empty" class="button" style="position: absolute; top: 340px; left: 120px; ">
-  <INPUT type="button" value="Empty"/>
- </SPAN>
- <SPAN id="feed" class="link" style="position: absolute; top: 340px; left: 240px; ">
-  <A href="shoppingCart/">
-   <SPAN>(feed)</SPAN>
-  </A>
- </SPAN>
-</DIV>
diff --git a/modules/edit/apps/store3/app.composite b/modules/edit/apps/store3/app.composite
deleted file mode 100644
index 735052f..0000000
--- a/modules/edit/apps/store3/app.composite
+++ /dev/null
@@ -1,60 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- * 
- *   http://www.apache.org/licenses/LICENSE-2.0
- * 
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.    
--->
-<composite xmlns="http://docs.oasis-open.org/ns/opencsa/sca/200912" xmlns:t="http://tuscany.apache.org/xmlns/sca/1.1" targetNamespace="http://store" name="store">
- <service name="Store" promote="Store"/>
- <service name="ShoppingCart" promote="ShoppingCart"/>
- <component name="Store" t:color="green1">
-  <t:implementation.python script="store.py"/>
-  <service name="Widget">
-   <t:binding.http uri="store"/>
-  </service>
-  <reference name="catalog" target="Catalog"/>
-  <reference name="shoppingCart" target="ShoppingCart"/>
-  <reference name="shoppingTotal" target="ShoppingCart"/>
- </component>
- <component name="Catalog" t:color="yellow1">
-  <t:implementation.python script="fruits-catalog.py"/>
-  <property>USD</property>
-  <service name="Catalog">
-   <t:binding.jsonrpc uri="catalog"/>
-  </service>
-  <reference name="currencyConverter" t:align="bottom" target="CurrencyConverter"/>
- </component>
- <component name="ShoppingCart" t:color="magenta1">
-  <t:implementation.python script="shopping-cart.py"/>
-  <service name="ShoppingCart">
-   <t:binding.http uri="shoppingCart"/>
-  </service>
-  <reference name="cache" target="Cache"/>
- </component>
- <component name="CurrencyConverter" t:color="blue1">
-  <t:implementation.python script="currency-converter.py"/>
-  <service name="CurrencyConverter" t:align="top">
-   <t:binding.jsonrpc uri="currencyConverter"/>
-  </service>
- </component>
- <component name="Cache" t:color="orange1">
-  <implementation.cpp path="../../components/cache" library="libmemcache"/>
-  <service name="Cache">
-   <t:binding.atom uri="cache"/>
-  </service>
-  <property>localhost:11211</property>
- </component>
-</composite>
diff --git a/modules/edit/apps/store3/app.html b/modules/edit/apps/store3/app.html
deleted file mode 100644
index 593d0a6..0000000
--- a/modules/edit/apps/store3/app.html
+++ /dev/null
@@ -1,47 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- * 
- *   http://www.apache.org/licenses/LICENSE-2.0
- * 
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.    
--->
-<DIV id="page">
- <SPAN id="storeh1" class="h1" style="position: absolute; top: 0px; left: 0px; ">
-  <H1>Store</H1>
- </SPAN>
- <SPAN id="catalogh2" class="h2" style="position: absolute; top: 40px; left: 0px; ">
-  <H2>Catalog</H2>
- </SPAN>
- <SPAN id="addToCart" class="button" style="position: absolute; top: 160px; left: 0px; ">
-  <INPUT type="button" value="Add to Cart"/>
- </SPAN>
- <SPAN id="carth2" class="h2" style="position: absolute; top: 200px; left: 0px; ">
-  <H2>Your Shopping Cart</H2>
- </SPAN>
- <SPAN id="total" class="text" style="position: absolute; top: 300px; left: 0px; ">
-  <SPAN>total</SPAN>
- </SPAN>
- <SPAN id="checkout" class="button" style="position: absolute; top: 340px; left: 0px; ">
-  <INPUT type="button" value="Checkout"/>
- </SPAN>
- <SPAN id="empty" class="button" style="position: absolute; top: 340px; left: 120px; ">
-  <INPUT type="button" value="Empty"/>
- </SPAN>
- <SPAN id="feed" class="link" style="position: absolute; top: 340px; left: 240px; ">
-  <A href="shoppingCart/">
-   <SPAN>(feed)</SPAN>
-  </A>
- </SPAN>
-</DIV>
diff --git a/modules/edit/apps/travel/app.composite b/modules/edit/apps/travel/app.composite
deleted file mode 100644
index 40a260e..0000000
--- a/modules/edit/apps/travel/app.composite
+++ /dev/null
@@ -1,181 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- * 
- *   http://www.apache.org/licenses/LICENSE-2.0
- * 
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.    
--->
-<composite xmlns="http://docs.oasis-open.org/ns/opencsa/sca/200912" xmlns:t="http://tuscany.apache.org/xmlns/sca/1.1" targetNamespace="http://tuscanyscatours.com/" name="travel">
- <service name="SCAToursUserInterface" promote="SCAToursUserInterface"/>
- <component name="SCAToursUserInterface" t:color="green1">
-  <t:implementation.widget location="scatours.html"/>
-  <service name="Widget">
-   <t:binding.http uri="/scatours"/>
-  </service>
-  <reference name="scaToursCatalog" target="SCATours/SCAToursSearch" t:align="bottom">
-   <t:binding.jsonrpc></t:binding.jsonrpc>
-  </reference>
- </component>
- <component name="SCATours">
-  <implementation.java class="com.tuscanyscatours.impl.SCAToursImpl"/>
-  <service name="SCAToursSearch" t:align="top">
-   <t:binding.jsonrpc></t:binding.jsonrpc>
-  </service>
-  <reference name="travelCatalogSearch" target="TravelCatalog/TravelCatalogSearch"/>
-  <reference name="tripBooking" target="TripBooking"/>
-  <reference name="cartCheckout" target="ShoppingCart/CartCheckout"/>
- </component>
- <component name="CreditCardPayment">
-  <implementation.java class="com.tuscanyscatours.payment.creditcard.impl.CreditCardPaymentImpl"/>
-  <service name="CreditCardPayment">
-   <interface.wsdl interface="http://www.tuscanyscatours.com/CreditCardPayment/#wsdl.interface(CreditCardPayment)"/>
-   <binding.ws uri="http://localhost:8082/CreditCardPayment" requires="authentication"/>
-   <binding.sca></binding.sca>
-  </service>
- </component>
- <component name="CurrencyConverter">
-  <implementation.java class="com.tuscanyscatours.currencyconverter.impl.CurrencyConverterImpl"/>
-  <service name="CurrencyConverter"/>
- </component>
- <component name="HotelPartner" t:color="orange1">
-  <implementation.java class="com.tuscanyscatours.hotel.impl.HotelImpl"/>
-  <service name="Search">
-   <binding.ws name="searchws" uri="http://localhost:8086/Hotel/Search"/>
-   <callback>
-    <binding.ws></binding.ws>
-   </callback>
-  </service>
-  <service name="Book"/>
- </component>
- <component name="FlightPartner" t:color="orange1">
-  <implementation.java class="com.tuscanyscatours.flight.impl.FlightImpl"/>
-  <service name="Search">
-   <interface.java interface="com.tuscanyscatours.common.Search" callbackInterface="com.tuscanyscatours.common.SearchCallback"/>
-   <binding.ws name="searchws" uri="http://localhost:8086/Flight/Search"/>
-   <t:binding.jsonrpc name="searchjsonrpc"/>
-   <callback>
-    <binding.ws></binding.ws>
-   </callback>
-  </service>
-  <service name="Book"/>
- </component>
- <component name="CarPartner" t:color="orange1">
-  <implementation.java class="com.tuscanyscatours.car.impl.CarImpl"/>
-  <service name="Search">
-   <binding.ws name="searchws" uri="http://localhost:8086/Car/Search"/>
-   <t:binding.jsonrpc name="searchjsonrpc"/>
-   <callback>
-    <binding.ws></binding.ws>
-   </callback>
-  </service>
-  <service name="Book"/>
- </component>
- <component name="TravelCatalog">
-  <implementation.java class="com.tuscanyscatours.travelcatalog.impl.TravelCatalogImpl"/>
-  <service name="TravelCatalogSearch"/>
-  <reference name="hotelSearch" target="HotelSearch">
-   <binding.ws uri="http://localhost:8086/Hotel/Search"/>
-   <callback>
-    <binding.ws name="callback" uri="http://localhost:8084/Hotel/SearchCallback"/>
-   </callback>
-  </reference>
-  <reference name="flightSearch" target="FlightSearch">
-   <interface.java interface="com.tuscanyscatours.common.Search" callbackInterface="com.tuscanyscatours.common.SearchCallback"/>
-   <binding.ws uri="http://localhost:8086/Flight/Search"/>
-   <callback>
-    <binding.ws name="callback" uri="http://localhost:8084/Flight/SearchCallback"/>
-   </callback>
-  </reference>
-  <reference name="carSearch" target="CarSearch">
-   <binding.ws uri="http://localhost:8086/Car/Search"/>
-   <callback>
-    <binding.ws name="callback" uri="http://localhost:8084/Car/SearchCallback"/>
-   </callback>
-  </reference>
-  <reference name="tripSearch" target="TripSearch">
-   <binding.ws uri="http://localhost:8085/Trip/Search"/>
-   <callback>
-    <binding.ws name="callback" uri="http://localhost:8084/Trip/SearchCallback"/>
-   </callback>
-  </reference>
-  <reference name="currencyConverter" target="CurrencyConverter"/>
-  <property>GBP</property>
- </component>
- <component name="TripBooking">
-  <implementation.java class="com.tuscanyscatours.tripbooking.impl.TripBookingImpl"/>
-  <service name="TripBooking"/>
-  <reference name="hotelBook" target="HotelPartner/Book"/>
-  <reference name="flightBook" target="FlightPartner/Book"/>
-  <reference name="carBook" target="CarPartner/Book"/>
-  <reference name="tripBook" target="TripPartner/Book"/>
-  <reference name="cartUpdates" target="ShoppingCart/CartUpdates"/>
- </component>
- <component name="TripPartner" t:color="orange1">
-  <implementation.java class="com.tuscanyscatours.trip.impl.TripImpl"/>
-  <service name="Search">
-   <binding.ws name="searchws" uri="http://localhost:8085/Trip/Search"/>
-   <t:binding.jsonrpc name="searchjsonrpc"/>
-   <callback>
-    <binding.ws></binding.ws>
-   </callback>
-  </service>
-  <service name="Book"/>
- </component>
- <component name="ShoppingCart">
-  <implementation.java class="com.tuscanyscatours.shoppingcart.impl.ShoppingCartImpl"/>
-  <reference name="cartStore" target="CartStore" t:align="bottom"/>
-  <reference name="payment" target="Payment">
-   <binding.ws uri="http://localhost:8081/Payment"/>
-  </reference>
- </component>
- <component name="CartStore" t:color="yellow1">
-  <service name="CartStore" t:align="top"/>
-  <implementation.java class="com.tuscanyscatours.shoppingcart.impl.CartStoreImpl"/>
- </component>
- <component name="Payment">
-  <implementation.spring location="Payment-context.xml"/>
-  <service name="Payment">
-   <binding.ws uri="http://localhost:8081/Payment"/>
-  </service>
-  <reference name="creditCardPaymentReference" target="CreditCardPayment">
-   <binding.ws uri="http://localhost:8082/CreditCardPayment" requires="authentication"/>
-  </reference>
-  <reference name="emailGateway" target="EmailGateway"/>
-  <reference name="customerRegistry" target="CustomerRegistry"/>
-  <property>1.23</property>
- </component>
- <component name="CustomerRegistry">
-  <implementation.java class="com.tuscanyscatours.customer.impl.CustomerRegistryImpl"/>
- </component>
- <component name="EmailGateway">
-  <implementation.java class="com.tuscanyscatours.emailgateway.impl.EmailGatewayImpl"/>
- </component>
- <component name="HotelSearch" t:color="red1">
-  <service name="HotelSearch"/>
-  <implementation.java class="com.tuscanyscatours.PlaceHolderImpl"/>
- </component>
- <component name="FlightSearch" t:color="red1">
-  <service name="FlightSearch"/>
-  <implementation.java class="com.tuscanyscatours.PlaceHolderImpl"/>
- </component>
- <component name="CarSearch" t:color="red1">
-  <service name="CarSearch"/>
-  <implementation.java class="com.tuscanyscatours.PlaceHolderImpl"/>
- </component>
- <component name="TripSearch" t:color="red1">
-  <service name="TripSearch"/>
-  <implementation.java class="com.tuscanyscatours.PlaceHolderImpl"/>
- </component>
-</composite>
diff --git a/modules/edit/apps/travel/app.html b/modules/edit/apps/travel/app.html
deleted file mode 100644
index ff320ac..0000000
--- a/modules/edit/apps/travel/app.html
+++ /dev/null
@@ -1,27 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- * 
- *   http://www.apache.org/licenses/LICENSE-2.0
- * 
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.    
--->
-<DIV id="page">
- <SPAN id="header" class="h1" style="position: absolute; top: 0px; left: 0px; ">
-  <H1>Welcome to SCATours Online Travel</H1>
- </SPAN>
- <SPAN id="book" class="button" style="position: absolute; top: 60px; left: 0px; ">
-  <INPUT type="button" value="Book a Trip"/>
- </SPAN>
-</DIV>
diff --git a/modules/edit/dashboard.py b/modules/edit/dashboard.py
index 825bf8b..4dd48cc 100644
--- a/modules/edit/dashboard.py
+++ b/modules/edit/dashboard.py
@@ -34,7 +34,8 @@
 # Post a new app to the user's dashboard
 def post(collection, app, user, cache):
     id = (str(uuid.uuid1()),)
-    dashboard = cons((car(app), car(id), caddr(app)), getdashboard(dashboardid(user), cache))
+    newapp = list("'entry", cadr(car(app)), list("'id", id), cadddr(car(app)))
+    dashboard = cons(newapp, getdashboard(dashboardid(user), cache))
     cache.put(dashboardid(user), dashboard)
     return id
 
@@ -42,9 +43,9 @@
 def put(id, app, user, cache):
     def putapp(app, dashboard):
         if isNil(dashboard):
-            return (app,)
-        if cadr(app) == cadr(car(dashboard)):
-            return cons(app, cdr(dashboard))
+            return app
+        if cadr(caddr(car(app))) == cadr(caddr(car(dashboard))):
+            return cons(car(app), cdr(dashboard))
         return cons(car(dashboard), putapp(app, cdr(dashboard)))
 
     dashboard = putapp(app, getdashboard(dashboardid(user), cache))
@@ -56,12 +57,12 @@
     def findapp(id, dashboard):
         if isNil(dashboard):
             return None
-        if car(id) == cadr(car(dashboard)):
-            return car(dashboard)
+        if car(id) == cadr(caddr(car(dashboard))):
+            return (car(dashboard),)
         return findapp(id, cdr(dashboard))
 
     if isNil(id):
-        return ("Your Apps", user.id()) + getdashboard(dashboardid(user), cache)
+        return ((("'feed", ("'title", "Your Apps"), ("'id", user.id())) + getdashboard(dashboardid(user), cache)),)
     return findapp(id, getdashboard(dashboardid(user), cache))
 
 # Delete apps from the user's dashboard
@@ -72,7 +73,7 @@
     def deleteapp(id, dashboard):
         if isNil(dashboard):
             return ()
-        if car(id) == cadr(car(dashboard)):
+        if car(id) == cadr(caddr(car(dashboard))):
             return cdr(dashboard)
         return cons(car(dashboard), deleteapp(id, cdr(dashboard)))
 
diff --git a/modules/edit/dashboards/joe@localhost b/modules/edit/dashboards/joe@localhost
index 0d5faf0..5771c2f 100644
--- a/modules/edit/dashboards/joe@localhost
+++ b/modules/edit/dashboards/joe@localhost
@@ -1 +1 @@
-(("An App that shows my Aggregated Social Profile" "myprofile" ()) ("An advanced version of the Aggregated Social Profile App" "myprofile2" ()) ("An App that shows Friends Near Me" "nearme" ()) ("An advanced version of the Friends Near Me App" "nearme2" ()) ("Sample Online Store App" "store" ()) ("Layout Variation of the Online Store App" "store2" ()) ("Another Variation of the Online Store App" "store3" ()) ("Travel Tutorial App" "travel" ()) ("An Empty Test App" "test" ()) ("Test Values and Lists" "testvalues" ()) ("Test Social Components" "testsocial" ()) ("Test URL Components" "testurl" ()) ("Test Logic Components" "testlogic" ()) ("Test Text Processing Components" "testtext" ()))
\ No newline at end of file
+((entry (title "An Empty Test App") (id "test")) (entry (title "Test Values and Lists") (id "testvalues")) (entry (title "Test Social Components") (id "testsocial")) (entry (title "Test URL Components") (id "testurl")) (entry (title "Test Logic Components") (id "testlogic")) (entry (title "Test Text Processing Components") (id "testtext")) (entry (title "An App that shows my Social Profiles") (id "me360")) (entry (title "An App that shows Friends Near Me") (id "nearme")))
diff --git a/modules/edit/dashboards/joe@sca-store.com b/modules/edit/dashboards/joe@sca-store.com
index 0d5faf0..5771c2f 100644
--- a/modules/edit/dashboards/joe@sca-store.com
+++ b/modules/edit/dashboards/joe@sca-store.com
@@ -1 +1 @@
-(("An App that shows my Aggregated Social Profile" "myprofile" ()) ("An advanced version of the Aggregated Social Profile App" "myprofile2" ()) ("An App that shows Friends Near Me" "nearme" ()) ("An advanced version of the Friends Near Me App" "nearme2" ()) ("Sample Online Store App" "store" ()) ("Layout Variation of the Online Store App" "store2" ()) ("Another Variation of the Online Store App" "store3" ()) ("Travel Tutorial App" "travel" ()) ("An Empty Test App" "test" ()) ("Test Values and Lists" "testvalues" ()) ("Test Social Components" "testsocial" ()) ("Test URL Components" "testurl" ()) ("Test Logic Components" "testlogic" ()) ("Test Text Processing Components" "testtext" ()))
\ No newline at end of file
+((entry (title "An Empty Test App") (id "test")) (entry (title "Test Values and Lists") (id "testvalues")) (entry (title "Test Social Components") (id "testsocial")) (entry (title "Test URL Components") (id "testurl")) (entry (title "Test Logic Components") (id "testlogic")) (entry (title "Test Text Processing Components") (id "testtext")) (entry (title "An App that shows my Social Profiles") (id "me360")) (entry (title "An App that shows Friends Near Me") (id "nearme")))
diff --git a/modules/edit/htdocs/app/app.html b/modules/edit/htdocs/app/app.html
index c4bc54a..faf0372 100644
--- a/modules/edit/htdocs/app/app.html
+++ b/modules/edit/htdocs/app/app.html
@@ -36,7 +36,6 @@
 <th class="thl thr">Settings</th>
 
 <th class="thl thr" style="padding-top: 0px; padding-bottom: 0px; padding-right: 0px; text-align: right;">
-<span id="source" style="font-weight: normal;">[atom]</span>
 <input type="button" id="saveButton" style="font-weight: bold;" Value="Saved"/>
 </th>
 </tr>
@@ -71,7 +70,6 @@
  * The current app name.
  */
 var appname = ui.queryParams()['app'];
-$('source').innerHTML = '[<a href="/apps/' + appname + '">atom</a>]';
 
 /**
  * The current app entry and corresponding saved XML content.
@@ -92,12 +90,13 @@
  */
 function getapp(name) {
     dashboard.get(name, function(doc) {
-        appentry = doc != null? atom.readATOMEntryDocument(doc) : mklist('', name);
-        $('appTitle').value = car(appentry) != ''? car(appentry) : deftitle;
+        appentry = doc != null? car(elementsToValues(atom.readATOMEntry(mklist(doc)))) : mklist("'entry", mklist("'title", ''), mklist("'id", name));
+        var title = cadr(assoc("'title", cdr(appentry)));
+        $('appTitle').value = title != ''? title : deftitle;
         $('appCategory').value = defcategory;
         $('appUpdated').innerHTML = defdate;
         $('appDescription').innerHTML = defdesc;
-        savedappentryxml = car(atom.writeATOMEntry(appentry));
+        savedappentryxml = car(atom.writeATOMEntry(valuesToElements(mklist(appentry))));
     });
 }
 
@@ -114,10 +113,10 @@
 function save() {
     $('saveButton').value = 'Saving';
     var title = $('appTitle').value;
-    appentry = mklist(title != deftitle && title != ''? title : appname, appname, mklist());
-    savedappentryxml = car(atom.writeATOMEntry(appentry));
+    var appentry = mklist("'entry", mklist("'title", title != deftitle && title != ''? title : appname), mklist("'id", appname));
+    savedappentryxml = car(atom.writeATOMEntry(valuesToElements(mklist(appentry))));
     dashboard.put(appname, savedappentryxml, function() {
-        if (savedappentryxml == car(atom.writeATOMEntry(appentry)))
+        if (savedappentryxml == car(atom.writeATOMEntry(valuesToElements(mklist(appentry)))))
             $('saveButton').value = 'Saved';
         return true;
     });
@@ -129,14 +128,14 @@
  */
 function onappchange() {
     var title = $('appTitle').value;
-    appentry = mklist(title != deftitle && title != ''? title : appname, appname, mklist());
-    if (savedappentryxml == car(atom.writeATOMEntry(appentry)))
+    var appentry = mklist("'entry", mklist("'title", title != deftitle && title != ''? title : appname), mklist("'id", appname));
+    if (savedappentryxml == car(atom.writeATOMEntry(valuesToElements(mklist(appentry)))))
         return false;
     $('saveButton').value = 'Save now';
 
     // Autosave after 3 seconds
     setTimeout(function() {
-        if (savedappentryxml == car(atom.writeATOMEntry(appentry)))
+        if (savedappentryxml == car(atom.writeATOMEntry(valuesToElements(mklist(appentry)))))
             return false;
         return save();
     }, 3000);
diff --git a/modules/edit/htdocs/dash/dashboard.html b/modules/edit/htdocs/dash/dashboard.html
index 3307d19..a261f75 100644
--- a/modules/edit/htdocs/dash/dashboard.html
+++ b/modules/edit/htdocs/dash/dashboard.html
@@ -79,20 +79,14 @@
         var apps = '<table style="width: 100%;">';
         apps += '<tr><th class="thl thr">App</th>' +
             '<th class="thr thl">Title</th>' +
-            '<th class="thr thl" style="padding-top: 4px; padding-bottom: 4px; padding-right: 2px; text-align: right;">' +
-            '<span style="font-weight: normal;">' + 
-            '[<a href="/dashboard">atom</a> <a href="/dashboardcache/joe@localhost">json</a>]' +
-            '</span></th></tr>';
+            '<th class="thr thl" style="padding-top: 4px; padding-bottom: 4px; padding-right: 2px; text-align: right;"></th></tr>';
 
-        var entries = cddr(atom.readATOMFeedDocument(doc));
+        var feed = car(elementsToValues(atom.readATOMFeed(mklist(doc))));
+        var entries = cadr(assoc("'entry", cdr(feed)));
         for (var i = 0; i < length(entries); i++) {
             var entry = entries[i];
-            var item = caddr(entry);
-            var composite = cddr(item);
-            var comps = scdl.components(composite);
-
-            name = cadr(entry);
-            title = car(entry);
+            title = cadr(assoc("'title", entry))
+            name = cadr(assoc("'id", entry))
 
             apps += '<tr>';
             apps += '<td><a href=\"' + '/graph/?app=' + name + '\" target=\"_parent\">' + name + '</a></td>';
@@ -142,8 +136,8 @@
     if (name == '')
         return false;
     var title = $('appTitle').value;
-    var app = mklist(title != deftitle && title != ''? title : name, name, mklist());
-    var entry = atom.writeATOMEntry(app);
+    var app = mklist(mklist("'entry", mklist("'title", title != deftitle && title != ''? title : name), mklist("'id", name)));
+    var entry = atom.writeATOMEntry(valuesToElements(app));
     dashboard.put(name, car(entry));
     getapps();
     $('newApp').style.visibility = 'hidden';
diff --git a/modules/edit/htdocs/graph/graph.html b/modules/edit/htdocs/graph/graph.html
index 2a92a5d1..4a973a1 100644
--- a/modules/edit/htdocs/graph/graph.html
+++ b/modules/edit/htdocs/graph/graph.html
@@ -43,7 +43,6 @@
 </th>
 
 <th class="thl thr" style="padding-top: 0px; padding-bottom: 0px; padding-right: 0px; text-align: right;">
-<span id="source" style="font-weight: normal;">[atom json]</span>
 <input type="button" id="saveButton" style="font-weight: bold;" Value="Saved"/>
 </th>
 </tr>
@@ -67,7 +66,6 @@
  * The current app name.
  */
 var appname = ui.queryParams()['app'];
-$('source').innerHTML = '[<a href="/apps/' + appname + '">atom</a> <a href="/appcache/' + appname + '/app.composite">json</a>]';
 
 /**
  * The current app composite and corresponding saved XML content.
@@ -79,9 +77,13 @@
  * Return the composite in an ATOM entry.
  */
 function atomcomposite(doc) {
-    var entry = atom.readATOMEntryDocument(doc);
-    var item = caddr(entry);
-    return cddr(item);
+    var entry = atom.readATOMEntry(mklist(doc));
+    if (isNil(entry))
+        return mklist();
+    var content = namedElementChild("'content", car(entry));
+    if (content == null)
+        return mklist();
+    return elementChildren(content);
 }
 
 /**
@@ -151,8 +153,8 @@
     $('saveButton').value = 'Saving';
     savedcomposxml = car(writeXML(composite, false));
     var entry = '<entry xmlns="http://www.w3.org/2005/Atom">' +
-        '<title type="text">' + appname + '</title><id>' + appname + '</id><content type="application/xml"><item>' +
-        savedcomposxml + '</item></content></entry>';
+        '<title type="text">' + appname + '</title><id>' + appname + '</id><content type="application/xml">' +
+        savedcomposxml + '</content></entry>';
     apps.put(appname, entry, function() {
         if (savedcomposxml == car(writeXML(composite, false)))
             $('saveButton').value = 'Saved';
diff --git a/modules/edit/htdocs/page/page.html b/modules/edit/htdocs/page/page.html
index 7ace732..297e5c5 100644
--- a/modules/edit/htdocs/page/page.html
+++ b/modules/edit/htdocs/page/page.html
@@ -42,7 +42,6 @@
 </th>
 
 <th class="thl thr" style="padding-top: 0px; padding-bottom: 0px; padding-right: 0px; text-align: right;">
-<span id="source" style="font-weight: normal;">[atom json]</span>
 <input type="button" id="saveButton" style="font-weight: bold;" Value="Saved"/>
 </th>
 </tr>
@@ -80,15 +79,18 @@
  * The current app name.
  */
 var appname = ui.queryParams()['app'];
-$('source').innerHTML = '[<a href="/pages/' + appname + '">atom</a> <a href="/appcache/' + appname + '/app.html">json</a>]';
 
 /**
  * Return the page in an ATOM entry.
  */
 function atompage(doc) {
-    var entry = atom.readATOMEntryDocument(doc);
-    var item = caddr(entry);
-    return cddr(item);
+    var entry = atom.readATOMEntry(mklist(doc));
+    if (isNil(entry))
+        return mklist();
+    var content = namedElementChild("'content", car(entry));
+    if (content == null)
+        return mklist();
+    return elementChildren(content);
 }
 
 /**
@@ -180,8 +182,8 @@
 
     // Update the page ATOM entry
     var entry = '<entry xmlns="http://www.w3.org/2005/Atom">' +
-        '<title type="text">' + appname + '</title><id>' + appname + '</id><content type="application/xml"><item>' +
-        savedpagexhtml + '</item></content></entry>';
+        '<title type="text">' + appname + '</title><id>' + appname + '</id><content type="application/xml">' +
+        savedpagexhtml + '</content></entry>';
 
     pages.put(appname, entry, function(e) {
         if (savedpagexhtml == pagexhtml())
diff --git a/modules/edit/pages.py b/modules/edit/pages.py
index e96e503..1fe475b 100644
--- a/modules/edit/pages.py
+++ b/modules/edit/pages.py
@@ -28,21 +28,24 @@
 # Post a new app page to the apps db
 def post(collection, app, cache):
     id = appid((str(uuid.uuid1()),))
-    xhtml = caddr(app);
+    xhtml = cdr(cadddr(car(app)))
     cache.put((id,), xhtml)
     return id
 
 # Put an app page into the apps db
 def put(id, app, cache):
-    xhtml = caddr(app);
+    xhtml = cdr(cadddr(car(app)))
     cache.put(appid(id), xhtml)
     return True
 
 # Get an app page from the apps db
 def get(id, cache):
     if isNil(id):
-        return ("Pages", "pages")
-    return (car(id), car(id), cache.get(appid(id)))
+        return (("'feed", ("'title", "Pages"), ("'id", "pages")),)
+    xhtml = cache.get(appid(id))
+    if (isNil(xhtml) or xhtml is None):
+        return (("'entry", ("'title", car(id)), ("'id", car(id))),)
+    return (("'entry", ("'title", car(id)), ("'id", car(id)), ("'content", car(xhtml))),)
 
 # Delete an app page from the apps db
 def delete(id, cache):
diff --git a/modules/edit/palettes.py b/modules/edit/palettes.py
index 9d07973..7872bb3 100644
--- a/modules/edit/palettes.py
+++ b/modules/edit/palettes.py
@@ -27,6 +27,6 @@
 # Get a palette from the palettes db
 def get(id, cache):
     if isNil(id):
-        return ("Palettes", "palettes")
-    return (car(id), car(id), cache.get(paletteid(id)))
+        return (("'feed", ("'title", "Palettes"), ("'id", "palettes")),)
+    return (("'entry", ("'title", car(id)), ("'id", car(id)), ("'content", car(cache.get(paletteid(id))))),)
 
diff --git a/modules/edit/util.py b/modules/edit/util.py
index 80bc7db..24467fd 100644
--- a/modules/edit/util.py
+++ b/modules/edit/util.py
@@ -43,6 +43,12 @@
 def caddr(l):
     return car(cddr(l))
 
+def cdddr(l):
+    return cdr(cdr(cdr(l)))
+
+def cadddr(l):
+    return car(cdddr(l))
+
 def append(a, b):
     return a + b
 
diff --git a/modules/http/http.hpp b/modules/http/http.hpp
index e2327be..7050021 100644
--- a/modules/http/http.hpp
+++ b/modules/http/http.hpp
@@ -407,19 +407,19 @@
 
     if (atom::isATOMEntry(ls)) {
         // Read an ATOM entry
-        const value val(atom::entryValue(content(atom::readATOMEntry(ls))));
+        const value val(elementsToValues(content(atom::readATOMEntry(ls))));
         debug(val, "http::get::result");
         return val;
     }
     if (contains(ct, "application/atom+xml") || atom::isATOMFeed(ls)) {
         // Read an ATOM feed
-        const value val(atom::feedValues(content(atom::readATOMFeed(ls))));
+        const value val(elementsToValues(content(atom::readATOMFeed(ls))));
         debug(val, "http::get::result");
         return val;
     }
     if (contains(ct, "application/rss+xml") || rss::isRSSFeed(ls)) {
         // Read an RSS feed
-        const value val(rss::feedValues(content(rss::readRSSFeed(ls))));
+        const value val(elementsToValues(content(rss::readRSSFeed(ls))));
         debug(val, "http::get::result");
         return val;
     }
@@ -449,7 +449,7 @@
 const failable<value> post(const value& val, const string& url, const CURLSession& cs) {
 
     // Convert value to an ATOM entry
-    const failable<list<string> > entry = atom::writeATOMEntry(atom::entryValuesToElements(val));
+    const failable<list<string> > entry = atom::writeATOMEntry(valuesToElements(val));
     if (!hasContent(entry))
         return mkfailure<value>(reason(entry));
     debug(url, "http::post::url");
@@ -474,7 +474,7 @@
 const failable<value> put(const value& val, const string& url, const CURLSession& cs) {
 
     // Convert value to an ATOM entry
-    const failable<list<string> > entry = atom::writeATOMEntry(atom::entryValuesToElements(val));
+    const failable<list<string> > entry = atom::writeATOMEntry(valuesToElements(val));
     if (!hasContent(entry))
         return mkfailure<value>(reason(entry));
     debug(url, "http::put::url");
diff --git a/modules/java/org/apache/tuscany/IterableUtil.java b/modules/java/org/apache/tuscany/IterableUtil.java
index 6d559f3..2366d79 100644
--- a/modules/java/org/apache/tuscany/IterableUtil.java
+++ b/modules/java/org/apache/tuscany/IterableUtil.java
@@ -117,6 +117,13 @@
     }
 
     /**
+     * Return the cdr of the cdr of the cdr of a list.
+     */
+    public static <T> Iterable<T> cdddr(final Object l) {
+        return cdr(cdr(cdr(l)));
+    }
+
+    /**
      * Return the car of the cdr of the cdr of a list.
      */
     @SuppressWarnings("unchecked")
@@ -125,6 +132,24 @@
     }
 
     /**
+     * Return the car of the cdr of the cdr of the cdr of a list.
+     */
+    @SuppressWarnings("unchecked")
+    public static <T> T cadddr(final Object l) {
+        return (T)car(cdddr(l));
+    }
+
+    /**
+     * Appends a list and another list.
+     */
+    @SuppressWarnings("unchecked")
+    public static <T> Iterable<T> append(final Object a, final Object b) {
+        if (isNil(a))
+            return (Iterable<T>)b;
+        return cons(car(a), append(cdr(a), b));
+    }
+
+    /**
      * Return the first pair matching a key from a list of key value pairs.
      */
     public static <T> Iterable<T> assoc(final Object k, final Object l) {
@@ -352,6 +377,11 @@
             assert car(al) == Integer.valueOf(1);
             assert cadr(al) == Integer.valueOf(2);
             assert caddr(al) == Integer.valueOf(3);
+
+            final Iterable<Object> a = list(0, 1, 2);
+            final Iterable<Object> b = list(3, 4);
+            final Iterable<Object> ab = append(a, b);
+            assert ab.toString().equals("[0, 1, 2, 3, 4]");
             return true;
         }
     }
diff --git a/modules/java/test/ServerImpl.java b/modules/java/test/ServerImpl.java
index 9de68fd..ee25cf7 100644
--- a/modules/java/test/ServerImpl.java
+++ b/modules/java/test/ServerImpl.java
@@ -29,12 +29,16 @@
 
     public Iterable<?> get(final Iterable<String> id) {
         if (isNil(id))
-            return list("Sample Feed", "123456789",
-                    list("Item", "111", list(list("'name", "Apple"), list("'currencyCode", "USD"), list("'currencySymbol", "$"), list("'price", 2.99))),
-                    list("Item", "222", list(list("'name", "Orange"), list("'currencyCode", "USD"), list("'currencySymbol", "$"), list("'price", 3.55))),
-                    list("Item", "333", list(list("'name", "Pear"), list("'currencyCode", "USD"), list("'currencySymbol", "$"), list("'price", 1.55))));
-        final Iterable<?> entry = list(list("'name", "Apple"), list("'currencyCode", "USD"), list("'currencySymbol", "$"), list("'price", 2.99));
-        return list("Item", car(id), entry);
+            return list(list("'feed", list("'title", "Sample Feed"), list("'id", "123456789"), list("'entry", list(
+                    list(list("'title", "Item"), list("'id", "111"),
+                        list("'content", list("'item", list("'name", "Apple"), list("'currencyCode", "USD"), list("'currencySymbol", "$"), list("'price", 2.99)))),
+                    list(list("'title", "Item"), list("'id", "222"),
+                        list("'content", list("'item", list("'name", "Orange"), list("'currencyCode", "USD"), list("'currencySymbol", "$"), list("'price", 3.55)))),
+                    list(list("'title", "Item"), list("'id", "333"),
+                        list("'content", list("'item", list("'name", "Pear"), list("'currencyCode", "USD"), list("'currencySymbol", "$"), list("'price", 1.55))))))));
+
+        final Iterable<?> content = list("'content", list("'item", list("'name", "Apple"), list("'currencyCode", "USD"), list("'currencySymbol", "$"), list("'price", 2.99)));
+        return list(list("'entry", list("'title", "Item"), list("'id", car(id)), content));
     }
 
     public Iterable<String> post(final Iterable<String> collection, final Iterable<?> item) {
diff --git a/modules/js/htdocs/atomutil.js b/modules/js/htdocs/atomutil.js
index 21aa16e..182b698 100644
--- a/modules/js/htdocs/atomutil.js
+++ b/modules/js/htdocs/atomutil.js
@@ -25,22 +25,23 @@
 /**
  * Convert a list of elements to a list of values representing an ATOM entry.
  */
-atom.entryElementsToValues = function(e) {
+atom.entryElementValues = function(e) {
     var lt = filter(selector(mklist(element, "'title")), e);
     var t = isNil(lt)? '' : elementValue(car(lt));
     var li = filter(selector(mklist(element, "'id")), e);
     var i = isNil(li)? '' : elementValue(car(li));
     var lc = filter(selector(mklist(element, "'content")), e);
-    return mklist(t, i, elementValue(car(lc)));
+    return append(mklist(element, "'entry", mklist(element, "'title", t), mklist(element, "'id", i)),
+            isNil(lc)? mklist() : mklist(mklist(element, "'content", elementValue(car(lc)))))
 };
 
 /**
  * Convert a list of elements to a list of values representing ATOM entries.
  */
-atom.entriesElementsToValues = function(e) {
+atom.entriesElementValues = function(e) {
     if (isNil(e))
         return e;
-    return cons(atom.entryElementsToValues(car(e)), atom.entriesElementsToValues(cdr(e)));
+    return cons(atom.entryElementValues(car(e)), atom.entriesElementValues(cdr(e)));
 };
 
 /**
@@ -59,7 +60,7 @@
     var e = readXMLDocument(doc);
     if (isNil(e))
         return mklist();
-    return atom.entryElementsToValues(car(e));
+    return mklist(atom.entryElementValues(car(e)));
 };
 
 /**
@@ -70,14 +71,6 @@
 };
 
 /**
- * Convert a list of values representy an ATOM entry to a value.
- */
-atom.entryValue = function(e) {
-    var v = elementsToValues(mklist(caddr(e)));
-    return cons(car(e), (cadr(e), cdr(car(v))));
-};
-
-/**
  * Return true if a list of strings represents an ATOM feed.
  */
 atom.isATOMFeed = function(l) {
@@ -96,40 +89,32 @@
     var t = filter(selector(mklist(element, "'title")), car(f));
     var i = filter(selector(mklist(element, "'id")), car(f));
     var e = filter(selector(mklist(element, "'entry")), car(f));
-    if (isNil(e))
-        return mklist(elementValue(car(t)), elementValue(car(i)));
-    return cons(elementValue(car(t)), cons(elementValue(car(i)), atom.entriesElementsToValues(e)));
+    return mklist(append(
+                mklist(element, "'feed", mklist(element, "'title", elementValue(car(t))), mklist(element, "'id", elementValue(car(i)))),
+                atom.entriesElementValues(e)));
 };
 
 /**
  * Convert a list of strings to a list of values representing an ATOM feed.
  */
 atom.readATOMFeed = function(l) {
-    return atom.readAtomFeedDocument(parseXML(l));
-};
-
-/**
- * Convert an ATOM feed containing elements to an ATOM feed containing values.
- */
-atom.feedValues = function(e) {
-    function feedValuesLoop(e) {
-        if (isNil(e))
-            return e;
-        return cons(entryValue(car(e)), feedValuesLoop(cdr(e)));
-    }
-
-    return cons(car(e), cons(cadr(e), feedValuesLoop(cddr(e))));
+    return atom.readATOMFeedDocument(parseXML(l));
 };
 
 /**
  * Convert a list of values representy an ATOM entry to a list of elements.
  */
 atom.entryElement = function(l) {
-    return mklist(element, "'entry", mklist(attribute, "'xmlns", "http://www.w3.org/2005/Atom"),
-            mklist(element, "'title", mklist(attribute, "'type", "text"), car(l)),
-            mklist(element, "'id", cadr(l)),
-            mklist(element, "'content", mklist(attribute, "'type", (isList(caddr(l))? "application/xml" : "text")), caddr(l)),
-            mklist(element, "'link", mklist(attribute, "'href", cadr(l))));
+    var title = elementValue(namedElementChild("'title", l));
+    var id = elementValue(namedElementChild("'id", l));
+    var content = namedElementChild("'content", l);
+    var text = isNil(content)? false : elementHasValue(content);
+    return append(append(
+            mklist(element, "'entry", mklist(attribute, "'xmlns", "http://www.w3.org/2005/Atom"),
+            mklist(element, "'title", mklist(attribute, "'type", "text"), title), mklist(element, "'id", id)),
+            isNil(content)? mklist() :
+                append(mklist(element, "'content", mklist(attribute, "'type", text? "text" : "application/xml")), text? mklist(elementValue(content)) : elementChildren(content))),
+            mklist(element, "'link", mklist(attribute, "'href", id)));
 };
 
 /**
@@ -144,42 +129,37 @@
 /**
  * Convert a list of values representing an ATOM entry to an ATOM entry.
  */
-atom.writeATOMEntry = function(l) {
+atom.writeATOMEntry = function(ll) {
+    var l = isNil(ll)? ll : car(ll);
     return writeXML(mklist(atom.entryElement(l)), true);
 };
 
 /**
  * Convert a list of values representing an ATOM feed to an ATOM feed.
  */
-atom.writeATOMFeed = function(l) {
+atom.writeATOMFeed = function(ll) {
+    var l = isNil(ll)? ll : car(ll);
+    var lt = filter(selector(mklist(element, "'title")), l);
+    var t = isNil(lt)? '' : elementValue(car(lt));
+    var li = filter(selector(mklist(element, "'id")), l);
+    var i = isNil(li)? '' : elementValue(car(li));
     var f = mklist(element, "'feed", mklist(attribute, "'xmlns", "http://www.w3.org/2005/Atom"),
             mklist(element, "'title", mklist(attribute, "'type", "text"), car(l)),
             mklist(element, "'id", cadr(l)));
-    if (isNil(cddr(l)))
+
+    // Write ATOM entries
+    var le = filter(selector(mklist(element, "'entry")), l);
+    if (isNil(le))
         return writeXML(mklist(f), true);
-    var fe = append(f, atom.entriesElements(cddr(l)));
-    return writeXML(mklist(fe), true);
-};
 
-/**
- * Convert an ATOM entry containing a value to an ATOM entry containing an item element.
- */
-atom.entryValuesToElements = function(v) {
-    if (isList(caddr(v)))
-        return cons(car(v), cons(cadr(v), valuesToElements(mklist(cons("'item", caddr(v))))));
-    return cons(car(v), cons(cadr(v), valuesToElements(mklist(mklist("'item", caddr(v))))));
-};
-
-/**
- * Convert an ATOM feed containing values to an ATOM feed containing elements.
- */
-atom.feedValuesToElements = function(v) {
-    function feedValuesToElementsLoop(v) {
-        if (isNil(v))
-            return v;
-        return cons(atom.entryValuesToElements(car(v)), feedValuesToElementsLoop(cdr(v)));
+    // Write a single ATOM entry element with a list of values
+    if (!isNil(le) && !isNil(car(le)) && isList(car(caddr(car(le))))) {
+        var fe = append(f, atom.entriesElements(caddr(car(le))));
+        return writeXML(mklist(fe), true);
     }
 
-    return cons(car(v), cons(cadr(v), feedValuesToElementsLoop(cddr(v))));
+    // Write separate ATOM entry elements
+    var fe = append(f, atom.entriesElements(le));
+    return writeXML(mklist(fe), true);
 };
 
diff --git a/modules/js/htdocs/component.js b/modules/js/htdocs/component.js
index 835cc14..ecbcded 100644
--- a/modules/js/htdocs/component.js
+++ b/modules/js/htdocs/component.js
@@ -174,9 +174,8 @@
         HTTPBindingClient.charset = httpCharset(http);
 
     // Unmarshall the JSON response
-    var data = http.responseText;
     var obj;
-    eval("obj = " + data);
+    eval("obj = " + http.responseText);
     if(obj.error)
         throw new HTTPBindingClient.Exception(obj.error.code, obj.error.msg);
     var res = obj.result;
@@ -224,15 +223,6 @@
 };
 
 /**
- * Return the XML Document result from an XMLHTTPRequest.
- */
-HTTPBindingClient.xmlResult = function(http) {
-    if(!http.responseXML || http.responseXML.childNodes.length == 0)
-        return (new DOMParser()).parseFromString(http.responseText, "text/xml");
-    return http.responseXML;
-}
-
-/**
  * REST ATOMPub GET method.
  */
 HTTPBindingClient.prototype.get = function(id, cb) {
@@ -246,15 +236,9 @@
         http.onreadystatechange = function() {
             if (http.readyState == 4) {
                 // Pass the result or exception
-                if (http.status == 200) {
-                    var res = null;
-                    try {
-                        res = HTTPBindingClient.xmlResult(http);
-                    } catch (e) {
-                        cb(null, e);
-                    }
-                    cb(res);
-                } else
+                if (http.status == 200)
+                    cb(http.responseText);
+                else
                     cb(null, new HTTPBindingClient.Exception(http.status, http.statusText));
             }
         };
@@ -267,7 +251,7 @@
     // Send the request and return the result or exception
     http.send(null);
     if (http.status == 200)
-        return HTTPBindingClient.xmlResult(http);
+        return http.responseText;
     throw new HTTPBindingClient.Exception(http.status, http.statusText);
 };
 
@@ -286,15 +270,9 @@
         http.onreadystatechange = function() {
             // Pass the result or exception
             if (http.readyState == 4) {
-                if (http.status == 201) {
-                    var res = null;
-                    try {
-                        res = HTTPBindingClient.xmlResult(http);
-                    } catch (e) {
-                        cb(null, e);
-                    }
-                    cb(res);
-                } else
+                if (http.status == 201)
+                    cb(http.responseText);
+                else
                     cb(null, new HTTPBindingClient.Exception(http.status, http.statusText));
             }
         };
@@ -306,7 +284,7 @@
     // Send the request and return the result or exception
     http.send(entry);
     if (http.status == 201)
-        return HTTPBindingClient.xmlResult(http);
+        return http.responseText;
     throw new HTTPBindingClient.Exception(http.status, http.statusText);
 };
 
@@ -423,30 +401,6 @@
 };
 
 /**
- * DOM parser wrapper.
- */
-if (typeof DOMParser == "undefined") {
-    DOMParser = function() {}
-    
-    DOMParser.prototype.parseFromString = function (str, contentType) {
-        if (typeof ActiveXObject != "undefined") {
-            var d = new ActiveXObject("MSXML.DomDocument");
-            d.loadXML(str);
-            return d;
-        } else if (typeof XMLHttpRequest != "undefined") {
-            var req = new XMLHttpRequest;
-            req.open("GET", "data:" + (contentType || "application/xml") +
-                            ";charset=utf-8," + encodeURIComponent(str), false);
-            if (req.overrideMimeType) {
-                req.overrideMimeType(contentType);
-            }
-            req.send(null);
-            return req.responseXML;
-        }
-    }
-}
-
-/**
  * Public API.
  */
 
diff --git a/modules/js/htdocs/util.js b/modules/js/htdocs/util.js
index 336248d..20af741 100644
--- a/modules/js/htdocs/util.js
+++ b/modules/js/htdocs/util.js
@@ -52,14 +52,14 @@
     return cdr(cdr(l));
 }
 
-function cdddr(l) {
-    return cdr(cdr(cdr(l)));
-}
-
 function caddr(l) {
     return car(cddr(l));
 }
 
+function cdddr(l) {
+    return cdr(cdr(cdr(l)));
+}
+
 function cadddr(l) {
     return car(cdddr(l));
 }
@@ -164,13 +164,22 @@
 var rconsole;
 
 function log(v) {
-    if (rconsole) {
-        try {
-            rconsole.log(v);
-        } catch (e) {}
-    }
     try {
-        console.log(v);
+        var s = '';
+        for (i = 0; i < arguments.length; i++) {
+            s = s + writeValue(arguments[i]);
+            if (i < arguments.length)
+                s = s + ' ';
+        }
+
+        if (rconsole) {
+            try {
+                rconsole.log(s);
+            } catch (e) {}
+        }
+        try {
+            console.log(s);
+        } catch (e) {}
     } catch (e) {}
     return true;
 }
diff --git a/modules/python/eval.hpp b/modules/python/eval.hpp
index bf539fa..65cd7f0 100644
--- a/modules/python/eval.hpp
+++ b/modules/python/eval.hpp
@@ -66,17 +66,12 @@
             PyObject* sval = PyObject_Str(val);    
             string msg = string() + PyString_AsString(stype) + " : " + PyString_AsString(sval);
             Py_DECREF(stype);
-            Py_DECREF(sval);                                    
-            Py_DECREF(type);
-            Py_DECREF(val);
-            Py_XDECREF(trace);
+            Py_DECREF(sval);
+            PyErr_Restore(type, val, trace);
             PyErr_Print();
             return msg;
         }
-        PyErr_Print();
-        Py_XDECREF(type);
-        Py_XDECREF(val);
-        Py_XDECREF(trace);
+        PyErr_Restore(type, val, trace);
         PyErr_Print();
         return "Unknown Python error";
     }
diff --git a/modules/python/server-test.py b/modules/python/server-test.py
index 29404c3..da5d216 100644
--- a/modules/python/server-test.py
+++ b/modules/python/server-test.py
@@ -24,13 +24,13 @@
 
 def get(id):
     if id == ():
-        return ("Sample Feed", "123456789",
-            ("Item", "111", (("'name", "Apple"), ("'currencyCode", "USD"), ("'currencySymbol", "$"), ("'price", 2.99))),
-            ("Item", "222", (("'name", "Orange"), ("'currencyCode", "USD"), ("'currencySymbol", "$"), ("'price", 3.55))),
-            ("Item", "333", (("'name", "Pear"), ("'currencyCode", "USD"), ("'currencySymbol", "$"), ("'price", 1.55))))
-        
-    entry = (("'name", "Apple"), ("'currencyCode", "USD"), ("'currencySymbol", "$"), ("'price", 2.99))
-    return ("Item", id[0], entry)
+        return (("'feed", ("'title", "Sample Feed"), ("'id", "123456789"), ("'entry", 
+            ((("'title", "Item"), ("'id", "111"), ("'content", ("'item", ("'name", "Apple"), ("'currencyCode", "USD"), ("'currencySymbol", "$"), ("'price", 2.99)))),
+             (("'title", "Item"), ("'id", "222"), ("'content", ("'item", ("'name", "Orange"), ("'currencyCode", "USD"), ("'currencySymbol", "$"), ("'price", 3.55)))),
+             (("'title", "Item"), ("'id", "333"), ("'content", ("'item", ("'name", "Pear"), ("'currencyCode", "USD"), ("'currencySymbol", "$"), ("'price", 1.55))))))),)
+
+    content = ("'content", ("'item", ("'name", "Apple"), ("'currencyCode", "USD"), ("'currencySymbol", "$"), ("'price", 2.99)))
+    return (("'entry", ("'title", "Item"), ("'id", id[0]), content),)
 
 def post(collection, item):
     return ("123456789",)
diff --git a/modules/rss/rss-test.cpp b/modules/rss/rss-test.cpp
index c2c3eb9..b30792b 100644
--- a/modules/rss/rss-test.cpp
+++ b/modules/rss/rss-test.cpp
@@ -88,19 +88,27 @@
         const list<value> i = list<value>() + element + value("item")
                 + value(list<value>() + element + value("name") + value(string("Apple")))
                 + value(list<value>() + element + value("price") + value(string("$2.99")));
-        const list<value> a = mklist<value>(string("fruit"), string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b"), i);
+        const list<value> a = list<value>() + (list<value>() + element + value("entry")
+                + value(list<value>() + element + value("title") + value(string("fruit")))
+                + value(list<value>() + element + value("id") + value(string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b")))
+                + value(list<value>() + element + value("content") + value(i)));
         ostringstream os;
         writeRSSEntry<ostream*>(writer, &os, a);
         assert(str(os) == itemEntry);
     }
     {
-        const list<value> a = mklist<value>(string("fruit"), string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b"), "Apple");
+        const list<value> a = list<value>() + (list<value>() + element + value("entry")
+                + value(list<value>() + element + value("title") + value(string("fruit")))
+                + value(list<value>() + element + value("id") + value(string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b")))
+                + value(list<value>() + element + value("content") + value(string("Apple"))));
         ostringstream os;
         writeRSSEntry<ostream*>(writer, &os, a);
         assert(str(os) == itemTextEntry);
     }
     {
-        const list<value> a = mklist<value>(string("fruit"), string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b"), list<value>());
+        const list<value> a = list<value>() + (list<value>() + element + value("entry")
+                + value(list<value>() + element + value("title") + value(string("fruit")))
+                + value(list<value>() + element + value("id") + value(string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b"))));
         ostringstream os;
         writeRSSEntry<ostream*>(writer, &os, a);
         assert(str(os) == itemNoDescriptionEntry);
@@ -172,8 +180,11 @@
 
 bool testFeed() {
     {
+        const list<value> a = list<value>() + (list<value>() + element + value("feed")
+                + value(list<value>() + element + value("title") + value(string("Feed")))
+                + value(list<value>() + element + value("id") + value(string("1234"))));
         ostringstream os;
-        writeRSSFeed<ostream*>(writer, &os, mklist<value>("Feed", "1234"));
+        writeRSSFeed<ostream*>(writer, &os, a);
         assert(str(os) == emptyFeed);
     }
     {
@@ -183,31 +194,29 @@
         assert(str(os) == emptyFeed);
     }
     {
-        const list<value> i = list<value>()
-                + (list<value>() + "fruit" + "cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b"
-                    + (list<value>() + element + "item"
+        const list<value> i1 = list<value>() + element + "item"
                         + (list<value>() + element + "name" + "Apple")
-                        + (list<value>() + element + "price" + "$2.99")))
-                + (list<value>() + "fruit" + "cart-53d67a61-aa5e-4e5e-8401-39edeba8b83c"
-                    + (list<value>() + element + "item"
+                        + (list<value>() + element + "price" + "$2.99");
+
+        const list<value> i2 = list<value>() + element + "item"
                         + (list<value>() + element + "name" + "Orange")
-                        + (list<value>() + element + "price" + "$3.55")));
-        const list<value> a = cons<value>("Feed", cons<value>("1234", i));
-        ostringstream os;
-        writeRSSFeed<ostream*>(writer, &os, a);
-        assert(str(os) == itemFeed);
-    }
-    {
+                        + (list<value>() + element + "price" + "$3.55");
+
         const list<value> i = list<value>()
-                + (list<value>() + "fruit" + "cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b"
-                    + valueToElement(list<value>() + "item"
-                        + (list<value>() + "name" + "Apple")
-                        + (list<value>() + "price" + "$2.99")))
-                + (list<value>() + "fruit" + "cart-53d67a61-aa5e-4e5e-8401-39edeba8b83c"
-                    + valueToElement(list<value>() + "item"
-                        + (list<value>() + "name" + "Orange")
-                        + (list<value>() + "price" + "$3.55")));
-        const list<value> a = cons<value>("Feed", cons<value>("1234", i));
+            + value(list<value>() + element + value("entry")
+                + value(list<value>() + element + value("title") + value(string("fruit")))
+                + value(list<value>() + element + value("id") + value(string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b")))
+                + value(list<value>() + element + value("content") + value(i1)))
+            + value(list<value>() + element + value("entry")
+                + value(list<value>() + element + value("title") + value(string("fruit")))
+                + value(list<value>() + element + value("id") + value(string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83c")))
+                + value(list<value>() + element + value("content") + value(i2)));
+        
+        const list<value> a = list<value>() + (append<value>(list<value>() + element + value("feed")
+                + value(list<value>() + element + value("title") + value(string("Feed")))
+                + value(list<value>() + element + value("id") + value("1234")),
+                i));
+
         ostringstream os;
         writeRSSFeed<ostream*>(writer, &os, a);
         assert(str(os) == itemFeed);
@@ -218,6 +227,12 @@
         writeRSSFeed<ostream*>(writer, &os, a);
         assert(str(os) == itemFeed);
     }
+    {
+        const list<value> a = elementsToValues(content(readRSSFeed(mklist(itemFeed))));
+        ostringstream os;
+        writeRSSFeed<ostream*>(writer, &os, valuesToElements(a));
+        assert(str(os) == itemFeed);
+    }
     return true;
 }
 
diff --git a/modules/rss/rss.hpp b/modules/rss/rss.hpp
index 646a8fd..c62d137 100644
--- a/modules/rss/rss.hpp
+++ b/modules/rss/rss.hpp
@@ -36,24 +36,33 @@
 namespace rss {
 
 /**
- * Convert a list of elements to a list of values representing an RSS entry.
+ * Tags used to tag feed and entry elements.
  */
-const list<value> entryElementsToValues(const list<value>& e) {
+const value feed("feed");
+const value entry("entry");
+
+/**
+ * Convert a list of elements to a list of element values representing an RSS entry.
+ */
+const list<value> entryElementValues(const list<value>& e) {
     const list<value> lt = filter<value>(selector(mklist<value>(element, "title")), e);
     const value t = isNil(lt)? value(emptyString) : elementValue(car(lt));
     const list<value> li = filter<value>(selector(mklist<value>(element, "link")), e);
     const value i = isNil(li)? value(emptyString) : elementValue(car(li));
     const list<value> ld = filter<value>(selector(mklist<value>(element, "description")), e);
-    return mklist<value>(t, i, isNil(ld)? (value)list<value>() : elementValue(car(ld)));
+    return append<value>(list<value>() + element + entry 
+                + value(list<value>() + element + value("title") + t)
+                + value(list<value>() + element + value("id") + i),
+                isNil(ld)? list<value>() : mklist<value>(value(list<value>() + element + value("content") + elementValue(car(ld)))));
 }
 
 /**
- * Convert a list of elements to a list of values representing RSS entries.
+ * Convert a list of elements to a list of element values representing ATOM entries.
  */
-const list<value> entriesElementsToValues(const list<value>& e) {
+const list<value> entriesElementValues(const list<value>& e) {
     if (isNil(e))
         return e;
-    return cons<value>(entryElementsToValues(car(e)), entriesElementsToValues(cdr(e)));
+    return cons<value>(entryElementValues(car(e)), entriesElementValues(cdr(e)));
 }
 
 /**
@@ -72,15 +81,7 @@
     const list<value> e = readXML(ilist);
     if (isNil(e))
         return mkfailure<list<value> >("Empty entry");
-    return entryElementsToValues(car(e));
-}
-
-/**
- * Convert a list of values representing an RSS entry to a value.
- */
-const value entryValue(const list<value>& e) {
-    const list<value> v = elementsToValues(mklist<value>(caddr(e)));
-    return cons(car(e), mklist<value>(cadr(e), isList(car(v))? (isNil((list<value>)car(v))? car(v) : (value)cdr<value>(car(v))) : car(v)));
+    return mklist<value>(entryElementValues(car(e)));
 }
 
 /**
@@ -94,34 +95,28 @@
     const list<value> t = filter<value>(selector(mklist<value>(element, "title")), car(c));
     const list<value> i = filter<value>(selector(mklist<value>(element, "link")), car(c));
     const list<value> e = filter<value>(selector(mklist<value>(element, "item")), car(c));
-    if (isNil(e))
-        return mklist<value>(elementValue(car(t)), elementValue(car(i)));
-    return cons<value>(elementValue(car(t)), cons(elementValue(car(i)), entriesElementsToValues(e)));
+    return mklist<value>(append<value>(list<value>() + element + feed 
+                + value(list<value>() + element + value("title") + elementValue(car(t)))
+                + value(list<value>() + element + value("id") + elementValue(car(i))),
+                entriesElementValues(e)));
 }
 
 /**
- * Convert an RSS feed containing elements to an RSS feed containing values.
- */
-const list<value> feedValuesLoop(const list<value> e) {
-    if (isNil(e))
-        return e;
-    return cons<value>(entryValue(car(e)), feedValuesLoop(cdr(e)));
-}
-
-const list<value> feedValues(const list<value>& e) {
-    return cons(car<value>(e), cons<value>(cadr<value>(e), feedValuesLoop(cddr<value>(e))));
-}
-
-/**
- * Convert a list of values representing an RSS entry to a list of elements.
- * The first two values in the list are the entry title and id.
+ * Convert a list of element values representing an RSS entry to a list of elements.
  */
 const list<value> entryElement(const list<value>& l) {
-    return list<value>()
+    const value title = elementValue(elementChild("title", l));
+    const value id = elementValue(elementChild("id", l));
+    const value content = elementChild("content", l);
+    const bool text = isNil(content)? false : elementHasValue(content);
+    return append<value>(list<value>()
         + element + "item"
-        + (list<value>() + element + "title" + car(l))
-        + (list<value>() + element + "link" + cadr(l))
-        + (isNil(cddr(l))? list<value>() : list<value>() + element + "description" + caddr(l));
+        + (list<value>() + element + "title" + title)
+        + (list<value>() + element + "link" + id),
+        isNil(content)?
+            list<value>() :
+            mklist<value>(append<value>(list<value>() + element + "description",
+                text? mklist<value>(elementValue(content)) : elementChildren(content))));
 }
 
 /**
@@ -137,7 +132,8 @@
  * Convert a list of values representing an RSS entry to an RSS entry.
  * The first two values in the list are the entry id and title.
  */
-template<typename R> const failable<R> writeRSSEntry(const lambda<R(const string&, const R)>& reduce, const R& initial, const list<value>& l) {
+template<typename R> const failable<R> writeRSSEntry(const lambda<R(const string&, const R)>& reduce, const R& initial, const list<value>& ll) {
+    const list<value> l = isNil(ll)? ll : (list<value>)car(ll);
     return writeXML<R>(reduce, initial, mklist<value>(entryElement(l)));
 }
 
@@ -152,12 +148,37 @@
  * Convert a list of values representing an RSS feed to an RSS feed.
  * The first two values in the list are the feed id and title.
  */
-template<typename R> const failable<R> writeRSSFeed(const lambda<R(const string&, const R)>& reduce, const R& initial, const list<value>& l) {
+template<typename R> const failable<R> writeRSSFeed(const lambda<R(const string&, const R)>& reduce, const R& initial, const list<value>& ll) {
+    const list<value> l = isNil(ll)? ll : (list<value>)car(ll);
+    const list<value> lt = filter<value>(selector(mklist<value>(element, "title")), l);
+    const value t = isNil(lt)? value(emptyString) : elementValue(car(lt));
+    const list<value> li = filter<value>(selector(mklist<value>(element, "id")), l);
+    const value i = isNil(li)? value(emptyString) : elementValue(car(li));
     const list<value> c = list<value>()
-        + (list<value>() + element + "title" + car(l))
-        + (list<value>() + element + "link" + cadr(l))
-        + (list<value>() + element + "description" + car(l));
-    const list<value> ce = isNil(cddr(l))? c : append(c, entriesElements(cddr(l)));
+        + (list<value>() + element + "title" + t)
+        + (list<value>() + element + "link" + i)
+        + (list<value>() + element + "description" + t);
+
+    // Write RSS entries
+    const list<value> le = filter<value>(selector(mklist<value>(element, entry)), l);
+    if (isNil(le)) {
+        const list<value> fe = list<value>()
+            + element + "rss" + (list<value>() + attribute + "version" + "2.0")
+            + append(list<value>() + element + "channel", c);
+        return writeXML<R>(reduce, initial, mklist<value>(fe));
+    }
+
+    // Write a single RSS entry element with a list of values
+    if (!isNil(le) && !isNil(car(le)) && isList(car<value>(caddr<value>(car(le))))) {
+        const list<value> ce = append(c, entriesElements(caddr<value>(car(le))));
+        const list<value> fe = list<value>()
+            + element + "rss" + (list<value>() + attribute + "version" + "2.0")
+            + append(list<value>() + element + "channel", ce);
+        return writeXML<R>(reduce, initial, mklist<value>(fe));
+    }
+
+    // Write separate RSS entry elements
+    const list<value> ce = append(c, entriesElements(le));
     const list<value> fe = list<value>()
         + element + "rss" + (list<value>() + attribute + "version" + "2.0")
         + append(list<value>() + element + "channel", ce);
@@ -175,26 +196,6 @@
     return reverse(list<string>(content(ls)));
 }
 
-/**
- * Convert an RSS entry containing a value to an RSS entry containing an item element.
- */
-const list<value> entryValuesToElements(const list<value> val) {
-    return cons(car(val), cons(cadr(val), valuesToElements(mklist<value>(cons<value>("item", (list<value>)caddr(val))))));
-}
-
-/**
- * Convert an RSS feed containing values to an RSS feed containing elements.
- */
-const list<value> feedValuesToElementsLoop(const list<value> val) {
-    if (isNil(val))
-        return val;
-    return cons<value>(entryValuesToElements(car(val)), feedValuesToElementsLoop(cdr(val)));
-}
-
-const list<value> feedValuesToElements(const list<value>& val) {
-    return cons(car<value>(val), cons<value>(cadr<value>(val), feedValuesToElementsLoop(cddr<value>(val))));
-}
-
 }
 }
 
diff --git a/modules/scheme/json-value.cpp b/modules/scheme/json-value.cpp
index 0ab9c85..d7ffc2b 100644
--- a/modules/scheme/json-value.cpp
+++ b/modules/scheme/json-value.cpp
@@ -39,8 +39,7 @@
         cerr << reason(lv);
         return 1;
     }
-    const value v = elementsToValues(content(lv));
-    cout << writeValue(v);
+    cout << writeValue(content(lv));
     return 0;
 }
 
diff --git a/modules/scheme/primitive.hpp b/modules/scheme/primitive.hpp
index 6f3f71f..899d6f8 100644
--- a/modules/scheme/primitive.hpp
+++ b/modules/scheme/primitive.hpp
@@ -145,26 +145,30 @@
     return mkuuid();
 }
 
-const value cadrProc(unused const list<value>& args) {
+const value cadrProc(const list<value>& args) {
     return cadr((list<value> )car(args));
 }
 
-const value caddrProc(unused const list<value>& args) {
+const value caddrProc(const list<value>& args) {
     return caddr((list<value> )car(args));
 }
 
-const value cadddrProc(unused const list<value>& args) {
+const value cadddrProc(const list<value>& args) {
     return cadddr((list<value> )car(args));
 }
 
-const value cddrProc(unused const list<value>& args) {
+const value cddrProc(const list<value>& args) {
     return cddr((list<value> )car(args));
 }
 
-const value cdddrProc(unused const list<value>& args) {
+const value cdddrProc(const list<value>& args) {
     return cdddr((list<value> )car(args));
 }
 
+const value appendProc(const list<value>& args) {
+    return append((list<value> )car(args), (list<value>)cadr(args));
+}
+
 const value startProc(unused const list<value>& args) {
     return lambda<value(const list<value>&)>();
 }
@@ -222,6 +226,7 @@
     + "cadddr"
     + "cddr"
     + "cdddr"
+    + "append"
     + "display"
     + "log"
     + "uuid"
@@ -247,6 +252,7 @@
     + primitiveProcedure(cadddrProc)
     + primitiveProcedure(cddrProc)
     + primitiveProcedure(cdddrProc)
+    + primitiveProcedure(appendProc)
     + primitiveProcedure(displayProc)
     + primitiveProcedure(logProc)
     + primitiveProcedure(uuidProc)
diff --git a/modules/scheme/value-json.cpp b/modules/scheme/value-json.cpp
index 40cc889..5045226 100644
--- a/modules/scheme/value-json.cpp
+++ b/modules/scheme/value-json.cpp
@@ -34,7 +34,7 @@
 
 int valueJSON() {
     const js::JSContext cx;
-    failable<list<string> > s = json::writeJSON(valuesToElements(readValue(cin)), cx);
+    failable<list<string> > s = json::writeJSON(readValue(cin), cx);
     if (!hasContent(s)) {
         cerr << reason(s);
         return 1;
diff --git a/modules/scheme/value-xml.cpp b/modules/scheme/value-xml.cpp
index 1508f7b..7091d5c 100644
--- a/modules/scheme/value-xml.cpp
+++ b/modules/scheme/value-xml.cpp
@@ -33,7 +33,7 @@
 namespace scheme {
 
 int valueXML() {
-    failable<list<string> > s = writeXML(valuesToElements(readValue(cin)));
+    failable<list<string> > s = writeXML(readValue(cin));
     if (!hasContent(s)) {
         cerr << reason(s);
         return 1;
diff --git a/modules/scheme/xml-value.cpp b/modules/scheme/xml-value.cpp
index 0b95174..d88f754 100644
--- a/modules/scheme/xml-value.cpp
+++ b/modules/scheme/xml-value.cpp
@@ -33,7 +33,7 @@
 namespace scheme {
 
 int xmlValue() {
-    const value v = elementsToValues(readXML(streamList(cin)));
+    const value v = readXML(streamList(cin));
     cout << writeValue(v);
     return 0;
 }
diff --git a/modules/server/client-test.hpp b/modules/server/client-test.hpp
index c17f012..dffdb89 100644
--- a/modules/server/client-test.hpp
+++ b/modules/server/client-test.hpp
@@ -132,10 +132,13 @@
 
 bool testPost() {
     gc_scoped_pool pool;
-    const list<value> i = list<value>()
+    const list<value> i = list<value>() + "content" + (list<value>() + "item"
             + (list<value>() + "name" + string("Apple"))
-            + (list<value>() + "price" + string("$2.99"));
-    const list<value> a = mklist<value>(string("item"), string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b"), i);
+            + (list<value>() + "price" + string("$2.99")));
+    const list<value> a = list<value>() + (list<value>() + "entry" 
+            + (list<value>() + "title" + string("item"))
+            + (list<value>() + "id" + string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b"))
+            + i);
     http::CURLSession ch("", "", "");
     const failable<value> id = http::post(a, testURI, ch);
     assert(hasContent(id));
@@ -173,20 +176,26 @@
     gc_scoped_pool pool;
     http::CURLSession ch("", "", "");
     {
-        const list<value> i = list<value>()
+        const list<value> i = list<value>() + "content" + (list<value>() + "item" 
             + (list<value>() + "name" + string("Apple"))
-            + (list<value>() + "price" + string("$2.99"));
-        const list<value> val = mklist<value>(string("item"), string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b"), i);
+            + (list<value>() + "price" + string("$2.99")));
+        const list<value> val = list<value>() + (list<value>() + "entry" 
+            + (list<value>() + "title" + string("item"))
+            + (list<value>() + "id" + string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b"))
+            + i);
         const lambda<bool()> pl = postLoop(testURI, val, ch);
         cout << "ATOMPub POST small test " << time(pl, 5, 200) << " ms" << endl;
     }
     if (testBlobs) {
-        const list<value> i = list<value>()
+        const list<value> i = list<value>() + "content" + (list<value>() + "item"
             + (list<value>() + "name" + string("Apple"))
             + (list<value>() + "blob1" + blob)
             + (list<value>() + "blob2" + blob)
-            + (list<value>() + "price" + string("$2.99"));
-        const list<value> val = mklist<value>(string("item"), string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b"), i);
+            + (list<value>() + "price" + string("$2.99")));
+        const list<value> val = list<value>() + (list<value>() + "entry" 
+            + (list<value>() + "title" + string("item"))
+            + (list<value>() + "id" + string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b"))
+            + i);
         const lambda<bool()> pl = postBlobLoop(testURI, val, ch);
         cout << "ATOMPub POST blob test  " << time(pl, 5, 200) << " ms" << endl;
     }
@@ -234,10 +243,13 @@
     const int count = 50;
     const int threads = 10;
 
-    const list<value> i = list<value>()
-        + (list<value>() + "name" + string("Apple"))
-        + (list<value>() + "price" + string("$2.99"));
-    const value val = mklist<value>(string("item"), string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b"), i);
+    const list<value> i = list<value>() + "content" + (list<value>() + "item"
+            + (list<value>() + "name" + string("Apple"))
+            + (list<value>() + "price" + string("$2.99")));
+    const value val = list<value>() + (list<value>() + "entry" 
+            + (list<value>() + "title" + string("item"))
+            + (list<value>() + "id" + string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b"))
+            + i);
 
     const lambda<bool()> pl= curry(lambda<bool(const string, const int, const value)>(postThread), testURI, count, val);
     const lambda<bool()> ptl = postThreadLoop(pl, threads);
@@ -294,10 +306,13 @@
     const int count = 50;
     const int procs = 10;
 
-    const list<value> i = list<value>()
-        + (list<value>() + "name" + string("Apple"))
-        + (list<value>() + "price" + string("$2.99"));
-    const value val = mklist<value>(string("item"), string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b"), i);
+    const list<value> i = list<value>() + "content" + (list<value>() + "item"
+            + (list<value>() + "name" + string("Apple"))
+            + (list<value>() + "price" + string("$2.99")));
+    const list<value> val = list<value>() + (list<value>() + "entry" 
+            + (list<value>() + "title" + string("item"))
+            + (list<value>() + "id" + string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b"))
+            + i);
 
     const lambda<bool()> pl= curry(lambda<bool(const string, const int, const value)>(postProc), testURI, count, val);
     const lambda<bool()> ptl = postForkLoop(pl, procs);
@@ -311,10 +326,13 @@
 
 const bool testPut() {
     gc_scoped_pool pool;
-    const list<value> i = list<value>()
+    const list<value> i = list<value>() + "content" + (list<value>() + "item"
             + (list<value>() + "name" + string("Apple"))
-            + (list<value>() + "price" + string("$2.99"));
-    const list<value> a = mklist<value>(string("item"), string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b"), i);
+            + (list<value>() + "price" + string("$2.99")));
+    const list<value> a = list<value>() + (list<value>() + "entry" 
+            + (list<value>() + "title" + string("item"))
+            + (list<value>() + "id" + string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b"))
+            + i);
     http::CURLSession ch("", "", "");
     value rc = content(http::put(a, testURI + "/111", ch));
     assert(rc == value(true));
diff --git a/modules/server/mod-eval.hpp b/modules/server/mod-eval.hpp
index 8047015..634bc59 100644
--- a/modules/server/mod-eval.hpp
+++ b/modules/server/mod-eval.hpp
@@ -143,27 +143,34 @@
         return httpd::writeResult(json::writeJSON(list<value>(), cx), "application/json", r);
     }
 
+    // Write content-type / content-list pair
+    if (isString(car<value>(c)) && !isNil(cdr<value>(c)) && isList(cadr<value>(c)))
+        return httpd::writeResult(convertValues<string>(cadr<value>(c)), car<value>(c), r);
+
     // Write an assoc value as a JSON result
     if (isSymbol(car<value>(c)) && !isNil(cdr<value>(c))) {
         js::JSContext cx;
         return httpd::writeResult(json::writeJSON(valuesToElements(mklist<value>(c)), cx), "application/json", r);
     }
 
-    // Write content-type / content-list pair
-    if (isString(car<value>(c)) && !isNil(cdr<value>(c)) && isList(cadr<value>(c)))
-        return httpd::writeResult(convertValues<string>(cadr<value>(c)), car<value>(c), r);
+    // Convert list of values to element values
+    const list<value> e = valuesToElements(c);
+    debug(e, "modeval::get::elements");
 
     // Write an ATOM feed or entry
-    if (isString(car<value>(c)) && !isNil(cdr<value>(c)) && isString(cadr<value>(c))) {
-        if (isNil(cddr(path)))
-            return httpd::writeResult(atom::writeATOMFeed(atom::feedValuesToElements(c)), "application/atom+xml", r);
-        else
-            return httpd::writeResult(atom::writeATOMEntry(atom::entryValuesToElements(c)), "application/atom+xml", r);
+    if (isList(car<value>(e)) && !isNil(car<value>(e))) {
+        const list<value> el = car<value>(e);
+        if (isSymbol(car<value>(el)) && car<value>(el) == element && !isNil(cdr<value>(el)) && isSymbol(cadr<value>(el))) {
+            if (cadr<value>(el) == atom::feed)
+                return httpd::writeResult(atom::writeATOMFeed(e), "application/atom+xml", r);
+            if (cadr<value>(el) == atom::entry)
+                return httpd::writeResult(atom::writeATOMEntry(e), "application/atom+xml", r);
+        }
     }
 
     // Write any other compound value as a JSON value
     js::JSContext cx;
-    return httpd::writeResult(json::writeJSON(valuesToElements(c), cx), "application/json", r);
+    return httpd::writeResult(json::writeJSON(e, cx), "application/json", r);
 }
 
 /**
@@ -210,7 +217,7 @@
             return rc;
         const list<string> ls = httpd::read(r);
         debug(ls, "modeval::post::input");
-        const value entry = atom::entryValue(content(atom::readATOMEntry(ls)));
+        const value entry = elementsToValues(content(atom::readATOMEntry(ls)));
 
         // Evaluate the POST expression
         const failable<value> val = failableResult(impl(cons<value>("post", mklist<value>(cddr(path), entry))));
@@ -245,7 +252,7 @@
         return rc;
     const list<string> ls = httpd::read(r);
     debug(ls, "modeval::put::input");
-    const value entry = atom::entryValue(content(atom::readATOMEntry(ls)));
+    const value entry = elementsToValues(content(atom::readATOMEntry(ls)));
 
     // Evaluate the PUT expression and update the corresponding resource
     const failable<value> val = failableResult(impl(cons<value>("put", mklist<value>(cddr(path), entry))));
diff --git a/modules/server/server-test.scm b/modules/server/server-test.scm
index c23adb7..4bbff6e 100644
--- a/modules/server/server-test.scm
+++ b/modules/server/server-test.scm
@@ -23,12 +23,12 @@
 
 (define (get id)
   (if (nul id)
-    '("Sample Feed" "123456789"
-      ("Item" "111" ((name "Apple") (currencyCode "USD") (currencySymbol "$") (price 2.99)))
-      ("Item" "222" ((name "Orange") (currencyCode "USD") (currencySymbol "$") (price 3.55)))
-      ("Item" "333" ((name "Pear") (currencyCode "USD") (currencySymbol "$") (price 1.55))))
+    '((feed (title "Sample Feed") (id "123456789") (entry
+       (((title "Item") (id "111") (content (item (name "Apple") (currencyCode "USD") (currencySymbol "$") (price 2.99))))
+        ((title "Item") (id "222") (content (item (name "Orange") (currencyCode "USD") (currencySymbol "$") (price 3.55))))
+        ((title "Item") (id "333") (content (item (name "Pear") (currencyCode "USD") (currencySymbol "$") (price 1.55))))))))
     
-    (list "Item" (car id) '((name "Apple") (currencyCode "USD") (currencySymbol "$") (price 2.99))))
+    (list (list 'entry '(title "Item") (list 'id (car id)) '(content (item (name "Apple") (currencyCode "USD") (currencySymbol "$") (price 2.99))))))
 )
 
 (define (post collection item)
diff --git a/modules/wsgi/atom-test.py b/modules/wsgi/atom-test.py
index 81a6106..9ada53b 100755
--- a/modules/wsgi/atom-test.py
+++ b/modules/wsgi/atom-test.py
@@ -71,7 +71,7 @@
 
 def testEntry():
     i = (element, "'item", (element, "'name", "Apple"), (element, "'price", "$2.99"))
-    a = ("item", "cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b", i)
+    a = ((element, "'entry", (element, "'title", "item"), (element, "'id", "cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b"), (element, "'content", i)),)
     s = writeATOMEntry(a);
     assert car(s) == itemEntry
 
@@ -123,41 +123,29 @@
     "</feed>\n"
 
 def testFeed():
-    s = writeATOMFeed(("Feed", "1234"))
+    a = ((element, "'feed", (element, "'title", "Feed"), (element, "'id", "1234")),)
+    s = writeATOMFeed(a)
     assert car(s) == emptyFeed
 
     a2 = readATOMFeed((emptyFeed,))
     s2 = writeATOMFeed(a2)
     assert car(s2) == emptyFeed
 
-    i3 = (("item", "cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b",
-            (element, "'item", (element, "'name", "Apple"), (element, "'price", "$2.99"))),
-          ("item", "cart-53d67a61-aa5e-4e5e-8401-39edeba8b83c",
-            (element, "'item", (element, "'name", "Orange"), (element, "'price", "$3.55"))))
-    a3 = cons("Feed", cons("1234", i3))
+    i3 = ((element, "'entry", (element, "'title", "item"), (element, "'id", "cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b"),
+            (element, "'content", (element, "'item", (element, "'name", "Apple"), (element, "'price", "$2.99")))),
+          (element, "'entry", (element, "'title", "item"), (element, "'id", "cart-53d67a61-aa5e-4e5e-8401-39edeba8b83c"),
+            (element, "'content", (element, "'item", (element, "'name", "Orange"), (element, "'price", "$3.55")))))
+    a3 = (append((element, "'feed", (element, "'title", "Feed"), (element, "'id", "1234")), i3),)
     s3 = writeATOMFeed(a3)
     assert car(s3) == itemFeed
 
-    i4 = (("item", "cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b",
-            valueToElement(("'item", ("'name", "Apple"), ("'price", "$2.99")))),
-          ("item", "cart-53d67a61-aa5e-4e5e-8401-39edeba8b83c",
-            valueToElement(("'item", ("'name", "Orange"), ("'price", "$3.55")))))
-    a4 = cons("Feed", cons("1234", i4))
-    s4 = writeATOMFeed(a4)
+    a4 = readATOMFeed((itemFeed,));
+    s4 = writeATOMFeed(a4);
     assert car(s4) == itemFeed
 
-    a5 = readATOMFeed((itemFeed,));
-    s5 = writeATOMFeed(a5);
+    a5 = elementsToValues(readATOMFeed((itemFeed,)));
+    s5 = writeATOMFeed(valuesToElements(a5));
     assert car(s5) == itemFeed
-
-    i6 = (("item", "cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b",
-            (("'name", "Apple"), ("'price", "$2.99"))),
-          ("item", "cart-53d67a61-aa5e-4e5e-8401-39edeba8b83c",
-            (("'name", "Orange"), ("'price", "$3.55"))))
-    a6 = cons("Feed", cons("1234", i6))
-    s6 = writeATOMFeed(feedValuesToElements(a6))
-    assert car(s6) == itemFeed
-
     return True
 
 if __name__ == "__main__":
diff --git a/modules/wsgi/atomutil.py b/modules/wsgi/atomutil.py
index 8e812ab..ad6425f 100644
--- a/modules/wsgi/atomutil.py
+++ b/modules/wsgi/atomutil.py
@@ -22,31 +22,27 @@
 from xmlutil import *
 
 # Convert a list of elements to a list of values representing an ATOM entry
-def entryElementsToValues(e):
+def entryElementValues(e):
     lt = filter(selector((element, "'title")), e)
     t = "" if isNil(lt) else elementValue(car(lt))
     li = filter(selector((element, "'id")), e)
     i = "" if isNil(li) else elementValue(car(li))
     lc = filter(selector((element, "'content")), e)
-    return (t, i, elementValue(car(lc)))
+    return append((element, "'entry", (element, "'title", t), (element, "'id", i)),
+            () if isNil(lc) else ((element, "'content", elementValue(car(lc))),))
 
 # Convert a list of elements to a list of values representing ATOM entries
-def entriesElementsToValues(e):
+def entriesElementValues(e):
     if isNil(e):
         return e
-    return cons(entryElementsToValues(car(e)), entriesElementsToValues(cdr(e)))
+    return cons(entryElementValues(car(e)), entriesElementValues(cdr(e)))
 
 # Convert a list of strings to a list of values representing an ATOM entry
 def readATOMEntry(l):
     e = readXML(l)
     if isNil(e):
         return ()
-    return entryElementsToValues(car(e))
-
-# Convert a list of values representing an ATOM entry to a value
-def entryValue(e):
-    v = elementsToValues((caddr(e),))
-    return cons(car(e), (cadr(e), cdr(car(v))))
+    return (entryElementValues(car(e)),)
 
 # Return true if a list of strings represents an ATOM feed
 def isATOMFeed(l):
@@ -68,26 +64,23 @@
     t = filter(selector((element, "'title")), car(f))
     i = filter(selector((element, "'id")), car(f))
     e = filter(selector((element, "'entry")), car(f))
-    if isNil(e):
-        return (elementValue(car(t)), elementValue(car(i)))
-    return cons(elementValue(car(t)), cons(elementValue(car(i)), entriesElementsToValues(e)))
-
-# Convert an ATOM feed containing elements to an ATOM feed containing values
-def feedValuesLoop(e):
-    if (isNil(e)):
-        return e
-    return cons(entryValue(car(e)), feedValuesLoop(cdr(e)))
-
-def feedValues(e):
-    return cons(car(e), cons(cadr(e), feedValuesLoop(cddr(e))))
+    return (append(
+                (element, "'feed", (element, "'title", elementValue(car(t))), (element, "'id", elementValue(car(i)))),
+                entriesElementValues(e)),)
 
 # Convert a list of values representy an ATOM entry to a list of elements
 def entryElement(l):
-    return (element, "'entry", (attribute, "'xmlns", "http://www.w3.org/2005/Atom"),
-            (element, "'title", (attribute, "'type", "text"), car(l)),
-            (element, "'id", cadr(l)),
-            (element, "'content", (attribute, "'type", ("application/xml" if isList(caddr(l)) else "text")), caddr(l)),
-            (element, "'link", (attribute, "'href", cadr(l))))
+    title = elementValue(namedElementChild("'title", l))
+    id = elementValue(namedElementChild("'id", l))
+    content = namedElementChild("'content", l)
+    text = False if isNil(content) else elementHasValue(content)
+    return append(append(
+            (element, "'entry", (attribute, "'xmlns", "http://www.w3.org/2005/Atom"),
+             (element, "'title", (attribute, "'type", "text"), title),
+             (element, "'id", id)),
+            () if isNil(content) else (append(
+                (element, "'content", (attribute, "'type", "text" if text else "application/xml")), (elementValue(content),) if text else elementChildren(content)),)),
+            ((element, "'link", (attribute, "'href", id)),))
 
 # Convert a list of values representing ATOM entries to a list of elements
 def entriesElements(l):
@@ -96,31 +89,32 @@
     return cons(entryElement(car(l)), entriesElements(cdr(l)))
 
 # Convert a list of values representing an ATOM entry to an ATOM entry
-def writeATOMEntry(l):
+def writeATOMEntry(ll):
+    l = ll if isNil(ll) else car(ll)
     return writeXML((entryElement(l),), True)
 
 # Convert a list of values representing an ATOM feed to an ATOM feed
-def writeATOMFeed(l):
+def writeATOMFeed(ll):
+    l = ll if isNil(ll) else car(ll)
+    lt = filter(selector((element, "'title")), l)
+    t = '' if isNil(lt) else elementValue(car(lt))
+    li = filter(selector((element, "'id")), l)
+    i = '' if isNil(li) else elementValue(car(li))
     f = (element, "'feed", (attribute, "'xmlns", "http://www.w3.org/2005/Atom"),
-            (element, "'title", (attribute, "'type", "text"), car(l)),
-            (element, "'id", cadr(l)))
-    if isNil(cddr(l)):
+            (element, "'title", (attribute, "'type", "text"), t),
+            (element, "'id", i))
+
+    # Write ATOM entries
+    le = filter(selector((element, "'entry")), l)
+    if isNil(le):
         return writeXML((f,), True)
-    fe = append(f, entriesElements(cddr(l)))
+
+    # Write a single ATOM entry element with a list of values
+    if not isNil(le) and not isNil(car(le)) and isList(car(caddr(car(le)))):
+        fe = append(f, entriesElements(caddr(car(le))))
+        return writeXML((fe,), True)
+
+    # Write separate ATOM entry elements
+    fe = append(f, entriesElements(le))
     return writeXML((fe,), True)
 
-# Convert an ATOM entry containing a value to an ATOM entry containing an item element
-def entryValuesToElements(v):
-    if isList(caddr(v)):
-        return cons(car(v), cons(cadr(v), valuesToElements((cons("'item", caddr(v)),))))
-    return cons(car(v), cons(cadr(v), valuesToElements((("'item", caddr(v)),))))
-
-# Convert an ATOM feed containing values to an ATOM feed containing elements
-def feedValuesToElementsLoop(v):
-    if isNil(v):
-        return v
-    return cons(entryValuesToElements(car(v)), feedValuesToElementsLoop(cdr(v)))
-
-def feedValuesToElements(v):
-    return cons(car(v), cons(cadr(v), feedValuesToElementsLoop(cddr(v))))
-
diff --git a/modules/wsgi/composite.py b/modules/wsgi/composite.py
index 28a38ad..baea7aa 100755
--- a/modules/wsgi/composite.py
+++ b/modules/wsgi/composite.py
@@ -179,18 +179,32 @@
     if m == "GET":
         v = comp("get", id)
         
+        # Write a simple value as a JSON value
+        if not isList(v):
+            return result(e, r, 200, (("Content-type", "application/json"),), writeJSON(valuesToElements((("'value", v),))))
+
+        # Write an empty list as a JSON empty value
+        if not isList(v):
+            return result(e, r, 200, (("Content-type", "application/json"),), writeJSON(()))
+
         # Write content-type / content-list pair
-        if isString(car(v)) and isList(cadr(v)):
+        if isString(car(v)) and not isNil(cdr(v)) and isList(cadr(v)):
             return result(e, r, 200, (("Content-type", car(v)),), cadr(v))
         
-        # Write an ATOM feed or entry
-        if isString(car(v)) and isString(cadr(v)):
-            if isNil(id):
-                return result(e, r, 200, (("Content-type", "application/atom+xml"),), writeATOMFeed(feedValuesToElements(v)))
-            return result(e, r, 200, (("Content-type", "application/atom+xml"),), writeATOMEntry(entryValuesToElements(v)))
+        # Convert list of values to element values
+        ve = valuesToElements(v)
+
+        # Write an assoc result as a JSON value
+        if isList(car(ve)) and not isNil(car(ve)):
+            el = car(ve)
+            if isSymbol(car(el)) and car(el) == element and not isNil(cdr(el)) and isSymbol(cadr(el)):
+                if cadr(el) == "'feed":
+                    return result(e, r, 200, (("Content-type", "application/atom+xml"),), writeATOMFeed(ve))
+                if cadr(el) == "'entry":
+                    return result(e, r, 200, (("Content-type", "application/atom+xml"),), writeATOMEntry(ve))
 
         # Write a JSON value
-        return result(e, r, 200, (("Content-type", "application/json"),), writeJSON(valuesToElements(v)))
+        return result(e, r, 200, (("Content-type", "application/json"),), writeJSON(ve))
 
     if m == "POST":
         ct = requestContentType(e)
@@ -208,7 +222,7 @@
 
         # Handle an ATOM entry POST
         if contains(ct, "application/atom+xml"):
-            ae = entryValue(readATOMEntry(requestBody(e)))
+            ae = elementsToValues(readATOMEntry(requestBody(e)))
             v = comp("post", id, ae)
             if isNil(v):
                 return failure(e, r, 500)
@@ -217,7 +231,7 @@
     
     if m == "PUT":
         # Handle an ATOM entry PUT
-        ae = entryValue(readATOMEntry(requestBody(e)))
+        ae = elementsToValues(readATOMEntry(requestBody(e)))
         v = comp("put", id, ae)
         if v == False:
             return failure(e, r, 404)
diff --git a/modules/wsgi/server-test.py b/modules/wsgi/server-test.py
index 28f88ef..610ec05 100644
--- a/modules/wsgi/server-test.py
+++ b/modules/wsgi/server-test.py
@@ -25,14 +25,15 @@
 def get(id):
     if id == ("index.html",):
         return ("text/plain", ("It works!",))
+
     if id == ():
-        return ("Sample Feed", "123456789",
-            ("Item", "111", (("'name", "Apple"), ("'currencyCode", "USD"), ("'currencySymbol", "$"), ("'price", 2.99))),
-            ("Item", "222", (("'name", "Orange"), ("'currencyCode", "USD"), ("'currencySymbol", "$"), ("'price", 3.55))),
-            ("Item", "333", (("'name", "Pear"), ("'currencyCode", "USD"), ("'currencySymbol", "$"), ("'price", 1.55))))
-        
-    entry = (("'name", "Apple"), ("'currencyCode", "USD"), ("'currencySymbol", "$"), ("'price", 2.99))
-    return ("Item", id[0], entry)
+        return (("'feed", ("'title", "Sample Feed"), ("'id", "123456789"), ("'entry", 
+            ((("'title", "Item"), ("'id", "111"), ("'content", ("'item", ("'name", "Apple"), ("'currencyCode", "USD"), ("'currencySymbol", "$"), ("'price", 2.99)))),
+             (("'title", "Item"), ("'id", "222"), ("'content", ("'item", ("'name", "Orange"), ("'currencyCode", "USD"), ("'currencySymbol", "$"), ("'price", 3.55)))),
+             (("'title", "Item"), ("'id", "333"), ("'content", ("'item", ("'name", "Pear"), ("'currencyCode", "USD"), ("'currencySymbol", "$"), ("'price", 1.55))))))),)
+
+    content = ("'content", ("'item", ("'name", "Apple"), ("'currencyCode", "USD"), ("'currencySymbol", "$"), ("'price", 2.99)))
+    return (("'entry", ("'title", "Item"), ("'id", id[0]), content),)
 
 def post(collection, item):
     return ("123456789",)
diff --git a/modules/wsgi/util.py b/modules/wsgi/util.py
index 80bc7db..24467fd 100644
--- a/modules/wsgi/util.py
+++ b/modules/wsgi/util.py
@@ -43,6 +43,12 @@
 def caddr(l):
     return car(cddr(l))
 
+def cdddr(l):
+    return cdr(cdr(cdr(l)))
+
+def cadddr(l):
+    return car(cdddr(l))
+
 def append(a, b):
     return a + b
 
diff --git a/samples/store-cluster/domains/jane/htdocs/index.html b/samples/store-cluster/domains/jane/htdocs/index.html
index 4cd219b..09e2c4a 100644
--- a/samples/store-cluster/domains/jane/htdocs/index.html
+++ b/samples/store-cluster/domains/jane/htdocs/index.html
@@ -22,8 +22,12 @@
 <meta name="apple-mobile-web-app-capable" content="yes"/>

 <meta name="apple-mobile-web-app-status-bar-style" content="black-translucent"/>

 <link rel="stylesheet" type="text/css" href="/ui.css"/>

-<title>Store</title>

+<title>Jane's Store</title>

 

+<script type="text/javascript" src="/util.js"></script>

+<script type="text/javascript" src="/elemutil.js"></script>

+<script type="text/javascript" src="/xmlutil.js"></script>

+<script type="text/javascript" src="/atomutil.js"></script>

 <script type="text/javascript" src="/component.js"></script>

 

 <script type="text/javascript">

@@ -50,8 +54,9 @@
 

 }

 

-function shoppingCart_getResponse(feed) {

-    if (feed != null) {

+function shoppingCart_getResponse(doc) {

+    if (doc != null) {

+        var feed = parseXML([doc]);

         var entries = feed.getElementsByTagName("entry"); 

         var list = "";

         for (var i=0; i<entries.length; i++) {

diff --git a/samples/store-cluster/domains/jane/shopping-cart.py b/samples/store-cluster/domains/jane/shopping-cart.py
index 44484ea..b3818a6 100644
--- a/samples/store-cluster/domains/jane/shopping-cart.py
+++ b/samples/store-cluster/domains/jane/shopping-cart.py
@@ -34,7 +34,7 @@
 # Post a new item to the cart, create a new cart if necessary
 def post(collection, item, cache, host, email):
     id = str(uuid.uuid1())
-    cart = ((item[0], id, item[2]),) + getcart(cartid(host, email), cache)
+    cart = (("'entry", item[0][1], ("'id", id), item[0][3]),) + getcart(cartid(host, email), cache)
     cache.put(cartid(host, email), cart)
     return (id,)
 
@@ -42,16 +42,16 @@
 # Find an item in the cart
 def find(id, cart):
     if cart == ():
-        return ("Item", "0", ())
-    elif id == cart[0][1]:
-        return cart[0]
+        return (("'entry", ("'title", "Item"), ("'id", 0)),)
+    elif id == cart[0][2][1]:
+        return (cart[0],)
     else:
         return find(id, cart[1:])
 
 # Get items from the cart
 def get(id, cache, host, email):
     if id == ():
-        return ("Your Cart", email.eval()) + getcart(cartid(host, email), cache)
+        return ((("'feed", ("'title", "Your Cart"), ("'id", email.eval())) + getcart(cartid(host,email), cache)),)
     return find(id[0], getcart(cartid(host, email), cache))
 
 # Delete items from the  cart
@@ -62,7 +62,7 @@
 
 # Return the price of an item
 def price(item):
-    return float(filter(lambda x: x[0] == "'price", item[2])[0][1])
+    return float(filter(lambda x: x[0] == "'price", item[3][1][1:])[0][1])
 
 # Sum the prices of a list of items
 def sum(items):
diff --git a/samples/store-cluster/domains/joe/htdocs/index.html b/samples/store-cluster/domains/joe/htdocs/index.html
index c32dcd9..4a25ff4 100644
--- a/samples/store-cluster/domains/joe/htdocs/index.html
+++ b/samples/store-cluster/domains/joe/htdocs/index.html
@@ -22,8 +22,12 @@
 <meta name="apple-mobile-web-app-capable" content="yes"/>

 <meta name="apple-mobile-web-app-status-bar-style" content="black-translucent"/>

 <link rel="stylesheet" type="text/css" href="/ui.css"/>

-<title>Store</title>

+<title>Joe's Store</title>

 

+<script type="text/javascript" src="/util.js"></script>

+<script type="text/javascript" src="/elemutil.js"></script>

+<script type="text/javascript" src="/xmlutil.js"></script>

+<script type="text/javascript" src="/atomutil.js"></script>

 <script type="text/javascript" src="/component.js"></script>

 

 <script type="text/javascript">

@@ -50,8 +54,9 @@
 

 }

 

-function shoppingCart_getResponse(feed) {

-    if (feed != null) {

+function shoppingCart_getResponse(doc) {

+    if (doc != null) {

+        var feed = parseXML([doc]);

         var entries = feed.getElementsByTagName("entry"); 

         var list = "";

         for (var i=0; i<entries.length; i++) {

diff --git a/samples/store-cluster/domains/joe/shopping-cart.py b/samples/store-cluster/domains/joe/shopping-cart.py
index 44484ea..b3818a6 100644
--- a/samples/store-cluster/domains/joe/shopping-cart.py
+++ b/samples/store-cluster/domains/joe/shopping-cart.py
@@ -34,7 +34,7 @@
 # Post a new item to the cart, create a new cart if necessary
 def post(collection, item, cache, host, email):
     id = str(uuid.uuid1())
-    cart = ((item[0], id, item[2]),) + getcart(cartid(host, email), cache)
+    cart = (("'entry", item[0][1], ("'id", id), item[0][3]),) + getcart(cartid(host, email), cache)
     cache.put(cartid(host, email), cart)
     return (id,)
 
@@ -42,16 +42,16 @@
 # Find an item in the cart
 def find(id, cart):
     if cart == ():
-        return ("Item", "0", ())
-    elif id == cart[0][1]:
-        return cart[0]
+        return (("'entry", ("'title", "Item"), ("'id", 0)),)
+    elif id == cart[0][2][1]:
+        return (cart[0],)
     else:
         return find(id, cart[1:])
 
 # Get items from the cart
 def get(id, cache, host, email):
     if id == ():
-        return ("Your Cart", email.eval()) + getcart(cartid(host, email), cache)
+        return ((("'feed", ("'title", "Your Cart"), ("'id", email.eval())) + getcart(cartid(host,email), cache)),)
     return find(id[0], getcart(cartid(host, email), cache))
 
 # Delete items from the  cart
@@ -62,7 +62,7 @@
 
 # Return the price of an item
 def price(item):
-    return float(filter(lambda x: x[0] == "'price", item[2])[0][1])
+    return float(filter(lambda x: x[0] == "'price", item[3][1][1:])[0][1])
 
 # Sum the prices of a list of items
 def sum(items):
diff --git a/samples/store-cpp/htdocs/index.html b/samples/store-cpp/htdocs/index.html
index 79996c6..83b1e16 100644
--- a/samples/store-cpp/htdocs/index.html
+++ b/samples/store-cpp/htdocs/index.html
@@ -24,6 +24,10 @@
 <link rel="stylesheet" type="text/css" href="/ui.css"/>

 <title>Store</title>

 

+<script type="text/javascript" src="/util.js"></script>

+<script type="text/javascript" src="/elemutil.js"></script>

+<script type="text/javascript" src="/xmlutil.js"></script>

+<script type="text/javascript" src="/atomutil.js"></script>

 <script type="text/javascript" src="/component.js"></script>

 

 <script type="text/javascript">

@@ -50,8 +54,9 @@
 

 }

 

-function shoppingCart_getResponse(feed) {

-    if (feed != null) {

+function shoppingCart_getResponse(doc) {

+    if (doc != null) {

+        var feed = parseXML([doc]);

         var entries = feed.getElementsByTagName("entry"); 

         var list = "";

         for (var i=0; i<entries.length; i++) {

diff --git a/samples/store-cpp/shopping-cart.cpp b/samples/store-cpp/shopping-cart.cpp
index 738ab2f..4b5dc8d 100644
--- a/samples/store-cpp/shopping-cart.cpp
+++ b/samples/store-cpp/shopping-cart.cpp
@@ -55,7 +55,7 @@
  */
 const failable<value> post(unused const list<value>& collection, const value& item, const lambda<value(const list<value>&)> cache) {
     const value id(mkuuid());
-    const list<value> newItem(mklist<value>(car<value>(item), id, caddr<value>(item)));
+    const list<value> newItem(mklist<value>("entry", cadr<value>(car<value>(item)), mklist<value>("id", id), cadddr<value>(car<value>(item))));
     const list<value> cart(cons<value>(newItem, getcart(cartId, cache)));
     cache(mklist<value>("put", mklist<value>(cartId), cart));
     return value(mklist<value>(id));
@@ -66,9 +66,9 @@
  */
 const value find(const value& id, const list<value>& cart) {
     if (isNil(cart))
-        return cons<value>(string("Item"), mklist<value>("0", list<value>()));
-    if (id == cadr<value>(car(cart)))
-        return car(cart);
+        return mklist<value>(mklist<value>("entry", mklist<value>("title", string("Item")), mklist<value>("id", "0")));
+    if (id == cadr<value>(caddr<value>(car(cart))))
+        return mklist<value>(car(cart));
     return find(id, cdr(cart));
 }
 
@@ -77,7 +77,7 @@
  */
 const failable<value> get(const list<value>& id, const lambda<value(const list<value>&)> cache) {
     if (isNil(id))
-        return value(append(mklist<value>(string("Your Cart"), cartId), getcart(cartId, cache)));
+        return value(mklist<value>(append(mklist<value>("feed", mklist<value>("title", string("Your Cart")), mklist<value>("id", cartId)), getcart(cartId, cache))));
     return find(car(id), getcart(cartId, cache));
 }
 
@@ -94,7 +94,7 @@
  * Return the price of an item.
  */
 const double price(const list<value>& item) {
-    return cadr<value>(assoc<value>("price", caddr(item)));
+    return cadr<value>(assoc<value>("price", cdr<value>(cadr<value>(cadddr(item)))));
 }
 
 /**
diff --git a/samples/store-gae/htdocs/index.html b/samples/store-gae/htdocs/index.html
index d4884cf..e16890e 100644
--- a/samples/store-gae/htdocs/index.html
+++ b/samples/store-gae/htdocs/index.html
@@ -24,6 +24,10 @@
 <link rel="stylesheet" type="text/css" href="/ui.css"/>

 <title>Store</title>

 

+<script type="text/javascript" src="/util.js"></script>

+<script type="text/javascript" src="/elemutil.js"></script>

+<script type="text/javascript" src="/xmlutil.js"></script>

+<script type="text/javascript" src="/atomutil.js"></script>

 <script type="text/javascript" src="/component.js"></script>

 

 <script type="text/javascript">

@@ -65,8 +69,9 @@
     document.getElementById('email').innerHTML = email;

 }

 

-function shoppingCart_getResponse(feed) {

-    if (feed != null) {

+function shoppingCart_getResponse(doc) {

+    if (doc != null) {

+        var feed = parseXML([doc]);

         var entries = feed.getElementsByTagName("entry"); 

         var list = "";

         for (var i=0; i<entries.length; i++) {

diff --git a/samples/store-gae/shopping-cart.py b/samples/store-gae/shopping-cart.py
index 3c3168d..11a55a5 100644
--- a/samples/store-gae/shopping-cart.py
+++ b/samples/store-gae/shopping-cart.py
@@ -32,23 +32,23 @@
 # Post a new item to the cart, create a new cart if necessary
 def post(collection, item, cache, host, email):
     id = str(uuid.uuid1())
-    cart = ((item[0], id, item[2]),) + getcart(cartId, cache)
+    cart = (("'entry", item[0][1], ("'id", id), item[0][3]),) + getcart(cartId, cache)
     cache.put((cartId,), cart)
     return (id,)
 
 # Find an item in the cart
 def find(id, cart):
     if cart == ():
-        return ("Item", "0", ())
-    elif id == cart[0][1]:
-        return cart[0]
+        return (("'entry", ("'title", "Item"), ("'id", 0)),)
+    elif id == cart[0][2][1]:
+        return (cart[0],)
     else:
         return find(id, cart[1:])
 
 # Get items from the cart
 def get(id, cache, host, email):
     if id == ():
-        return ("Your Cart", cartId) + getcart(cartId, cache)
+        return ((("'feed", ("'title", "Your Cart"), ("'id", cartId)) + getcart(cartId, cache)),)
     return find(id[0], getcart(cartId, cache))
 
 # Delete items from the  cart
@@ -59,7 +59,7 @@
 
 # Return the price of an item
 def price(item):
-    return float(filter(lambda x: x[0] == "'price", item[2])[0][1])
+    return float(filter(lambda x: x[0] == "'price", item[3][1][1:])[0][1])
 
 # Sum the prices of a list of items
 def sum(items):
diff --git a/samples/store-java/htdocs/index.html b/samples/store-java/htdocs/index.html
index 79996c6..83b1e16 100644
--- a/samples/store-java/htdocs/index.html
+++ b/samples/store-java/htdocs/index.html
@@ -24,6 +24,10 @@
 <link rel="stylesheet" type="text/css" href="/ui.css"/>

 <title>Store</title>

 

+<script type="text/javascript" src="/util.js"></script>

+<script type="text/javascript" src="/elemutil.js"></script>

+<script type="text/javascript" src="/xmlutil.js"></script>

+<script type="text/javascript" src="/atomutil.js"></script>

 <script type="text/javascript" src="/component.js"></script>

 

 <script type="text/javascript">

@@ -50,8 +54,9 @@
 

 }

 

-function shoppingCart_getResponse(feed) {

-    if (feed != null) {

+function shoppingCart_getResponse(doc) {

+    if (doc != null) {

+        var feed = parseXML([doc]);

         var entries = feed.getElementsByTagName("entry"); 

         var list = "";

         for (var i=0; i<entries.length; i++) {

diff --git a/samples/store-java/store/ShoppingCartImpl.java b/samples/store-java/store/ShoppingCartImpl.java
index e51beac..bd7678c 100644
--- a/samples/store-java/store/ShoppingCartImpl.java
+++ b/samples/store-java/store/ShoppingCartImpl.java
@@ -47,7 +47,7 @@
      */
     public Iterable<String> post(final Iterable<String> collection, final Iterable<?> item, final Service cache) {
         final String id = uuid();
-        final Iterable<?> newItem = list(car(item), id, caddr(item));
+        final Iterable<?> newItem = list("'entry", cadr(car(item)), list("'id", id), cadddr(car(item)));
         final Iterable<?> cart = cons(newItem, this.getcart(cartId, cache));
         final Iterable<String> iid = list(cartId);
         cache.put(iid, cart);
@@ -59,9 +59,9 @@
      */
     Iterable<?> find(final String id, final Iterable<?> cart) {
         if(isNil(cart))
-            return cons("Item", list("0", list()));
-        if(id.equals(cadr(car(cart))))
-            return car(cart);
+            return list(list("'entry", list("'title", "Item"), list("'id", "0")));
+        if(id.equals(cadr(caddr(car(cart)))))
+            return list(car(cart));
         return this.find(id, cdr(cart));
     }
 
@@ -70,7 +70,7 @@
      */
     public Iterable<?> get(final Iterable<String> id, final Service cache) {
         if(isNil(id))
-            return cons("Your Cart", cons(cartId, this.getcart(cartId, cache)));
+            return list(append(list("'feed", list("'title", "Your Cart"), list("'id", cartId)), this.getcart(cartId, cache)));
         return this.find((String)car(id), this.getcart(cartId, cache));
     }
 
@@ -89,7 +89,8 @@
      * Return the price of an item.
      */
     Double price(final Iterable<?> item) {
-        return Double.valueOf((String)cadr(assoc("'price", caddr(item))));
+        System.err.println("price!! " + cadr(cadddr(item)));
+        return Double.valueOf((String)cadr(assoc("'price", cdr(cadr(cadddr(item))))));
     }
 
     /**
diff --git a/samples/store-nosql/htdocs/index.html b/samples/store-nosql/htdocs/index.html
index 79996c6..83b1e16 100644
--- a/samples/store-nosql/htdocs/index.html
+++ b/samples/store-nosql/htdocs/index.html
@@ -24,6 +24,10 @@
 <link rel="stylesheet" type="text/css" href="/ui.css"/>

 <title>Store</title>

 

+<script type="text/javascript" src="/util.js"></script>

+<script type="text/javascript" src="/elemutil.js"></script>

+<script type="text/javascript" src="/xmlutil.js"></script>

+<script type="text/javascript" src="/atomutil.js"></script>

 <script type="text/javascript" src="/component.js"></script>

 

 <script type="text/javascript">

@@ -50,8 +54,9 @@
 

 }

 

-function shoppingCart_getResponse(feed) {

-    if (feed != null) {

+function shoppingCart_getResponse(doc) {

+    if (doc != null) {

+        var feed = parseXML([doc]);

         var entries = feed.getElementsByTagName("entry"); 

         var list = "";

         for (var i=0; i<entries.length; i++) {

diff --git a/samples/store-nosql/shopping-cart.scm b/samples/store-nosql/shopping-cart.scm
index 61b1694..e653f1e 100644
--- a/samples/store-nosql/shopping-cart.scm
+++ b/samples/store-nosql/shopping-cart.scm
@@ -31,7 +31,7 @@
 ; Post a new item to the cart, create a new cart if necessary
 (define (post collection item cache)
   (define id (uuid))
-  (define newItem (list (car item) id (caddr item)))
+  (define newItem (list 'entry (cadr (car item)) (list 'id id) (cadddr (car item))))
   (define cart (cons newItem (getcart cartId cache)))
   (cache "put" (list cartId) cart)
   (list id)
@@ -40,16 +40,16 @@
 ; Find an item in the cart
 (define (find id cart)
   (if (nul cart)
-    (cons "Item" (list "0" (list)))
-    (if (= id (cadr (car cart)))
-      (car cart)
+    (list (list 'entry (list 'title "Item") (list 'id "0")))
+    (if (= id (cadr (caddr (car cart))))
+      (list (car cart))
       (find id (cdr cart))))
 )
 
 ; Get items from the cart
 (define (get id cache)
   (if (nul id)
-    (cons "Your Cart" (cons cartId (getcart cartId cache)))
+    (list (append (list 'feed (list 'title "Your Cart") (list 'id cartId)) (getcart cartId cache)))
     (find (car id) (getcart cartId cache))
   )
 )
@@ -64,7 +64,7 @@
 
 ; Return the price of an item
 (define (price item)
-  (cadr (assoc 'price (caddr item)))
+  (cadr (assoc 'price (cadr (cadddr item))))
 )
 
 ; Sum the prices of a list of items
diff --git a/samples/store-python/htdocs/index.html b/samples/store-python/htdocs/index.html
index 79996c6..83b1e16 100644
--- a/samples/store-python/htdocs/index.html
+++ b/samples/store-python/htdocs/index.html
@@ -24,6 +24,10 @@
 <link rel="stylesheet" type="text/css" href="/ui.css"/>

 <title>Store</title>

 

+<script type="text/javascript" src="/util.js"></script>

+<script type="text/javascript" src="/elemutil.js"></script>

+<script type="text/javascript" src="/xmlutil.js"></script>

+<script type="text/javascript" src="/atomutil.js"></script>

 <script type="text/javascript" src="/component.js"></script>

 

 <script type="text/javascript">

@@ -50,8 +54,9 @@
 

 }

 

-function shoppingCart_getResponse(feed) {

-    if (feed != null) {

+function shoppingCart_getResponse(doc) {

+    if (doc != null) {

+        var feed = parseXML([doc]);

         var entries = feed.getElementsByTagName("entry"); 

         var list = "";

         for (var i=0; i<entries.length; i++) {

diff --git a/samples/store-python/shopping-cart.py b/samples/store-python/shopping-cart.py
index feb7398..1dac825 100644
--- a/samples/store-python/shopping-cart.py
+++ b/samples/store-python/shopping-cart.py
@@ -32,7 +32,7 @@
 # Post a new item to the cart, create a new cart if necessary
 def post(collection, item, cache):
     id = str(uuid.uuid1())
-    cart = ((item[0], id, item[2]),) + getcart(cartId, cache)
+    cart = (("'entry", item[0][1], ("'id", id), item[0][3]),) + getcart(cartId, cache)
     cache.put((cartId,), cart)
     return (id,)
 
@@ -40,16 +40,16 @@
 # Find an item in the cart
 def find(id, cart):
     if cart == ():
-        return ("Item", "0", ())
-    elif id == cart[0][1]:
-        return cart[0]
+        return (("'entry", ("'title", "Item"), ("'id", 0)),)
+    elif id == cart[0][2][1]:
+        return (cart[0],)
     else:
         return find(id, cart[1:])
 
 # Get items from the cart
 def get(id, cache):
     if id == ():
-        return ("Your Cart", cartId) + getcart(cartId, cache)
+        return ((("'feed", ("'title", "Your Cart"), ("'id", cartId)) + getcart(cartId, cache)),)
     return find(id[0], getcart(cartId, cache))
 
 # Delete items from the  cart
@@ -60,7 +60,7 @@
 
 # Return the price of an item
 def price(item):
-    return float(filter(lambda x: x[0] == "'price", item[2])[0][1])
+    return float(filter(lambda x: x[0] == "'price", item[3][1][1:])[0][1])
 
 # Sum the prices of a list of items
 def sum(items):
diff --git a/samples/store-scheme/htdocs/index.html b/samples/store-scheme/htdocs/index.html
index 79996c6..83b1e16 100644
--- a/samples/store-scheme/htdocs/index.html
+++ b/samples/store-scheme/htdocs/index.html
@@ -24,6 +24,10 @@
 <link rel="stylesheet" type="text/css" href="/ui.css"/>

 <title>Store</title>

 

+<script type="text/javascript" src="/util.js"></script>

+<script type="text/javascript" src="/elemutil.js"></script>

+<script type="text/javascript" src="/xmlutil.js"></script>

+<script type="text/javascript" src="/atomutil.js"></script>

 <script type="text/javascript" src="/component.js"></script>

 

 <script type="text/javascript">

@@ -50,8 +54,9 @@
 

 }

 

-function shoppingCart_getResponse(feed) {

-    if (feed != null) {

+function shoppingCart_getResponse(doc) {

+    if (doc != null) {

+        var feed = parseXML([doc]);

         var entries = feed.getElementsByTagName("entry"); 

         var list = "";

         for (var i=0; i<entries.length; i++) {

diff --git a/samples/store-scheme/shopping-cart.scm b/samples/store-scheme/shopping-cart.scm
index 61b1694..e653f1e 100644
--- a/samples/store-scheme/shopping-cart.scm
+++ b/samples/store-scheme/shopping-cart.scm
@@ -31,7 +31,7 @@
 ; Post a new item to the cart, create a new cart if necessary
 (define (post collection item cache)
   (define id (uuid))
-  (define newItem (list (car item) id (caddr item)))
+  (define newItem (list 'entry (cadr (car item)) (list 'id id) (cadddr (car item))))
   (define cart (cons newItem (getcart cartId cache)))
   (cache "put" (list cartId) cart)
   (list id)
@@ -40,16 +40,16 @@
 ; Find an item in the cart
 (define (find id cart)
   (if (nul cart)
-    (cons "Item" (list "0" (list)))
-    (if (= id (cadr (car cart)))
-      (car cart)
+    (list (list 'entry (list 'title "Item") (list 'id "0")))
+    (if (= id (cadr (caddr (car cart))))
+      (list (car cart))
       (find id (cdr cart))))
 )
 
 ; Get items from the cart
 (define (get id cache)
   (if (nul id)
-    (cons "Your Cart" (cons cartId (getcart cartId cache)))
+    (list (append (list 'feed (list 'title "Your Cart") (list 'id cartId)) (getcart cartId cache)))
     (find (car id) (getcart cartId cache))
   )
 )
@@ -64,7 +64,7 @@
 
 ; Return the price of an item
 (define (price item)
-  (cadr (assoc 'price (caddr item)))
+  (cadr (assoc 'price (cadr (cadddr item))))
 )
 
 ; Sum the prices of a list of items
diff --git a/samples/store-sql/htdocs/index.html b/samples/store-sql/htdocs/index.html
index 79996c6..83b1e16 100644
--- a/samples/store-sql/htdocs/index.html
+++ b/samples/store-sql/htdocs/index.html
@@ -24,6 +24,10 @@
 <link rel="stylesheet" type="text/css" href="/ui.css"/>

 <title>Store</title>

 

+<script type="text/javascript" src="/util.js"></script>

+<script type="text/javascript" src="/elemutil.js"></script>

+<script type="text/javascript" src="/xmlutil.js"></script>

+<script type="text/javascript" src="/atomutil.js"></script>

 <script type="text/javascript" src="/component.js"></script>

 

 <script type="text/javascript">

@@ -50,8 +54,9 @@
 

 }

 

-function shoppingCart_getResponse(feed) {

-    if (feed != null) {

+function shoppingCart_getResponse(doc) {

+    if (doc != null) {

+        var feed = parseXML([doc]);

         var entries = feed.getElementsByTagName("entry"); 

         var list = "";

         for (var i=0; i<entries.length; i++) {

diff --git a/samples/store-sql/shopping-cart.scm b/samples/store-sql/shopping-cart.scm
index 61b1694..e653f1e 100644
--- a/samples/store-sql/shopping-cart.scm
+++ b/samples/store-sql/shopping-cart.scm
@@ -31,7 +31,7 @@
 ; Post a new item to the cart, create a new cart if necessary
 (define (post collection item cache)
   (define id (uuid))
-  (define newItem (list (car item) id (caddr item)))
+  (define newItem (list 'entry (cadr (car item)) (list 'id id) (cadddr (car item))))
   (define cart (cons newItem (getcart cartId cache)))
   (cache "put" (list cartId) cart)
   (list id)
@@ -40,16 +40,16 @@
 ; Find an item in the cart
 (define (find id cart)
   (if (nul cart)
-    (cons "Item" (list "0" (list)))
-    (if (= id (cadr (car cart)))
-      (car cart)
+    (list (list 'entry (list 'title "Item") (list 'id "0")))
+    (if (= id (cadr (caddr (car cart))))
+      (list (car cart))
       (find id (cdr cart))))
 )
 
 ; Get items from the cart
 (define (get id cache)
   (if (nul id)
-    (cons "Your Cart" (cons cartId (getcart cartId cache)))
+    (list (append (list 'feed (list 'title "Your Cart") (list 'id cartId)) (getcart cartId cache)))
     (find (car id) (getcart cartId cache))
   )
 )
@@ -64,7 +64,7 @@
 
 ; Return the price of an item
 (define (price item)
-  (cadr (assoc 'price (caddr item)))
+  (cadr (assoc 'price (cadr (cadddr item))))
 )
 
 ; Sum the prices of a list of items
diff --git a/samples/store-vhost/domains/jane/htdocs/index.html b/samples/store-vhost/domains/jane/htdocs/index.html
index 4cd219b..09e2c4a 100644
--- a/samples/store-vhost/domains/jane/htdocs/index.html
+++ b/samples/store-vhost/domains/jane/htdocs/index.html
@@ -22,8 +22,12 @@
 <meta name="apple-mobile-web-app-capable" content="yes"/>

 <meta name="apple-mobile-web-app-status-bar-style" content="black-translucent"/>

 <link rel="stylesheet" type="text/css" href="/ui.css"/>

-<title>Store</title>

+<title>Jane's Store</title>

 

+<script type="text/javascript" src="/util.js"></script>

+<script type="text/javascript" src="/elemutil.js"></script>

+<script type="text/javascript" src="/xmlutil.js"></script>

+<script type="text/javascript" src="/atomutil.js"></script>

 <script type="text/javascript" src="/component.js"></script>

 

 <script type="text/javascript">

@@ -50,8 +54,9 @@
 

 }

 

-function shoppingCart_getResponse(feed) {

-    if (feed != null) {

+function shoppingCart_getResponse(doc) {

+    if (doc != null) {

+        var feed = parseXML([doc]);

         var entries = feed.getElementsByTagName("entry"); 

         var list = "";

         for (var i=0; i<entries.length; i++) {

diff --git a/samples/store-vhost/domains/jane/shopping-cart.py b/samples/store-vhost/domains/jane/shopping-cart.py
index feb7398..1dac825 100644
--- a/samples/store-vhost/domains/jane/shopping-cart.py
+++ b/samples/store-vhost/domains/jane/shopping-cart.py
@@ -32,7 +32,7 @@
 # Post a new item to the cart, create a new cart if necessary
 def post(collection, item, cache):
     id = str(uuid.uuid1())
-    cart = ((item[0], id, item[2]),) + getcart(cartId, cache)
+    cart = (("'entry", item[0][1], ("'id", id), item[0][3]),) + getcart(cartId, cache)
     cache.put((cartId,), cart)
     return (id,)
 
@@ -40,16 +40,16 @@
 # Find an item in the cart
 def find(id, cart):
     if cart == ():
-        return ("Item", "0", ())
-    elif id == cart[0][1]:
-        return cart[0]
+        return (("'entry", ("'title", "Item"), ("'id", 0)),)
+    elif id == cart[0][2][1]:
+        return (cart[0],)
     else:
         return find(id, cart[1:])
 
 # Get items from the cart
 def get(id, cache):
     if id == ():
-        return ("Your Cart", cartId) + getcart(cartId, cache)
+        return ((("'feed", ("'title", "Your Cart"), ("'id", cartId)) + getcart(cartId, cache)),)
     return find(id[0], getcart(cartId, cache))
 
 # Delete items from the  cart
@@ -60,7 +60,7 @@
 
 # Return the price of an item
 def price(item):
-    return float(filter(lambda x: x[0] == "'price", item[2])[0][1])
+    return float(filter(lambda x: x[0] == "'price", item[3][1][1:])[0][1])
 
 # Sum the prices of a list of items
 def sum(items):
diff --git a/samples/store-vhost/domains/joe/htdocs/index.html b/samples/store-vhost/domains/joe/htdocs/index.html
index c32dcd9..4a25ff4 100644
--- a/samples/store-vhost/domains/joe/htdocs/index.html
+++ b/samples/store-vhost/domains/joe/htdocs/index.html
@@ -22,8 +22,12 @@
 <meta name="apple-mobile-web-app-capable" content="yes"/>

 <meta name="apple-mobile-web-app-status-bar-style" content="black-translucent"/>

 <link rel="stylesheet" type="text/css" href="/ui.css"/>

-<title>Store</title>

+<title>Joe's Store</title>

 

+<script type="text/javascript" src="/util.js"></script>

+<script type="text/javascript" src="/elemutil.js"></script>

+<script type="text/javascript" src="/xmlutil.js"></script>

+<script type="text/javascript" src="/atomutil.js"></script>

 <script type="text/javascript" src="/component.js"></script>

 

 <script type="text/javascript">

@@ -50,8 +54,9 @@
 

 }

 

-function shoppingCart_getResponse(feed) {

-    if (feed != null) {

+function shoppingCart_getResponse(doc) {

+    if (doc != null) {

+        var feed = parseXML([doc]);

         var entries = feed.getElementsByTagName("entry"); 

         var list = "";

         for (var i=0; i<entries.length; i++) {

diff --git a/samples/store-vhost/domains/joe/shopping-cart.py b/samples/store-vhost/domains/joe/shopping-cart.py
index feb7398..1dac825 100644
--- a/samples/store-vhost/domains/joe/shopping-cart.py
+++ b/samples/store-vhost/domains/joe/shopping-cart.py
@@ -32,7 +32,7 @@
 # Post a new item to the cart, create a new cart if necessary
 def post(collection, item, cache):
     id = str(uuid.uuid1())
-    cart = ((item[0], id, item[2]),) + getcart(cartId, cache)
+    cart = (("'entry", item[0][1], ("'id", id), item[0][3]),) + getcart(cartId, cache)
     cache.put((cartId,), cart)
     return (id,)
 
@@ -40,16 +40,16 @@
 # Find an item in the cart
 def find(id, cart):
     if cart == ():
-        return ("Item", "0", ())
-    elif id == cart[0][1]:
-        return cart[0]
+        return (("'entry", ("'title", "Item"), ("'id", 0)),)
+    elif id == cart[0][2][1]:
+        return (cart[0],)
     else:
         return find(id, cart[1:])
 
 # Get items from the cart
 def get(id, cache):
     if id == ():
-        return ("Your Cart", cartId) + getcart(cartId, cache)
+        return ((("'feed", ("'title", "Your Cart"), ("'id", cartId)) + getcart(cartId, cache)),)
     return find(id[0], getcart(cartId, cache))
 
 # Delete items from the  cart
@@ -60,7 +60,7 @@
 
 # Return the price of an item
 def price(item):
-    return float(filter(lambda x: x[0] == "'price", item[2])[0][1])
+    return float(filter(lambda x: x[0] == "'price", item[3][1][1:])[0][1])
 
 # Sum the prices of a list of items
 def sum(items):