Index: /trunk/examples/objects/Makefile.in
===================================================================
--- /trunk/examples/objects/Makefile.in	(revision 1559)
+++ /trunk/examples/objects/Makefile.in	(revision 1560)
@@ -18,4 +18,5 @@
 		axis \
 		curve \
+		dxReader \
 		dxWriter \
 		floatBuffer \
Index: /trunk/examples/objects/app-fermi/fermi1.cc
===================================================================
--- /trunk/examples/objects/app-fermi/fermi1.cc	(revision 1559)
+++ /trunk/examples/objects/app-fermi/fermi1.cc	(revision 1560)
@@ -74,15 +74,12 @@
 
     // do it the easy way,
-    // create a plot to add to the library
+    // create a plot and add to the library
     // p1->add(nPts,xArr,yArr,format,curveLabel,curveDesc);
 
-    Rappture::Plot *p1 = new Rappture::Plot();
+    Rappture::Plot *p1 = new Rappture::Plot(lib);
     p1->add(nPts,fArr,EArr,"",curveLabel,curveDesc);
     p1.propstr("xlabel","Fermi-Dirac Factor");
     p1.propstr("ylabel","Energy");
     p1.propstr("yunits","eV");
-
-    // add the plot to the library
-    lib.put(p1);
 
 
@@ -91,5 +88,5 @@
     // c1->axis("xaxis","xlabel","xdesc","units","scale",dataArr,nPts);
 
-    Rappture::Curve *c1 = new Rappture::Curve("output.curve(FDF)");
+    Rappture::Curve *c1 = new Rappture::Curve(lib,"FDF");
     c1->label(curveLabel);
     c1->desc(curveDesc);
Index: /trunk/examples/objects/app-fermi/fermi2.cc
===================================================================
--- /trunk/examples/objects/app-fermi/fermi2.cc	(revision 1559)
+++ /trunk/examples/objects/app-fermi/fermi2.cc	(revision 1560)
@@ -25,10 +25,11 @@
     Rappture::Number *T  = NULL;
     Rappture::Number *Ef = NULL;
-    double E            = 0.0;
     double dE           = 0.0;
     double kT           = 0.0;
     double Emin         = 0.0;
     double Emax         = 0.0;
-    double f            = 0.0;
+    size_t nPts         = 200;
+    double E[nPts];
+    double f[nPts];
 
     // create a rappture library from the file filePath
@@ -55,18 +56,14 @@
     Emax = Ef->value("eV") + 10*kT;
 
-    dE = 0.005*(Emax-Emin);
+    dE = (1.0/nPts)*(Emax-Emin);
 
-    Rappture::SimpleDoubleBuffer fBuf;
-    Rappture::SimpleDoubleBuffer EBuf;
-
-    for (E = Emin; E < Emax; E = E + dE) {
+    E = Emin;
+    for (size_t idx = 0; idx < nPts; idx++) {
+        E = E + dE;
         f = 1.0/(1.0 + exp((E - Ef)/kT));
-        fBuf.append(f);
-        EBuf.append(E);
+        fArr[idx] = f;
+        EArr[idx] = E;
         rpUtilsProgress((int)((E-Emin)/(Emax-Emin)*100),"Iterating");
     }
-    const double *fArr = fBuf.data();
-    const double *EArr = EBuf.data();
-    size_t nPts = fBuf.nmemb();
 
     const char *curveLabel = "Fermi-Dirac Curve"
@@ -75,7 +72,8 @@
     // do it the easy way,
     // create a plot to add to the library
+    // plot is registered with lib upon object creation
     // p1->add(nPts,xArr,yArr,format,curveLabel,curveDesc);
 
-    Rappture::Plot *p1 = new Rappture::Plot();
+    Rappture::Plot *p1 = new Rappture::Plot(lib);
     p1->add(nPts,fArr,EArr,"",curveLabel,curveDesc);
     p1.propstr("xlabel","Fermi-Dirac Factor");
@@ -83,27 +81,11 @@
     p1.propstr("yunits","eV");
 
-    // add the plot to the library
-    lib.put(p1);
-
-
-    // or do it the harder way,
-    // create a curve to add to the library
-    // c1->axis("xaxis","xlabel","xdesc","units","scale",dataArr,nPts);
-
-    Rappture::Curve *c1 = new Rappture::Curve("output.curve(FDF)");
-    c1->label(curveLabel);
-    c1->desc(curveDesc);
-    c1->axis("xaxis","Fermi-Dirac Factor","","","",fArr,nPts);
-    c1->axis("yaxis","Energy","","eV","",EArr,nPts);
-
-    // add the curve to the library
-    lib.put(c1);
-
     lib.result();
 
     // clean up memory
     delete lib;
+    delete T;
+    delete Ef;
     delete p1;
-    delete c1;
 
     return 0;
Index: /trunk/examples/objects/app-fermi/fermi3.cc
===================================================================
--- /trunk/examples/objects/app-fermi/fermi3.cc	(revision 1560)
+++ /trunk/examples/objects/app-fermi/fermi3.cc	(revision 1560)
@@ -0,0 +1,86 @@
+// ----------------------------------------------------------------------
+//  EXAMPLE: Fermi-Dirac function in C++.
+//
+//  This simple example shows how to use Rappture within a simulator
+//  written in C++.
+// ======================================================================
+//  AUTHOR:  Derrick Kearney, Purdue University
+//  Copyright (c) 2005-2009  Purdue Research Foundation
+//
+//  See the file "license.terms" for information on usage and
+//  redistribution of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+// ======================================================================
+
+#include "rappture.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <math.h>
+#include <unistd.h>
+
+int main(int argc, char * argv[]) {
+
+    Rappture::Library lib;
+
+    Rappture::Number T;
+    Rappture::Number Ef;
+    double dE           = 0.0;
+    double kT           = 0.0;
+    double Emin         = 0.0;
+    double Emax         = 0.0;
+    size_t nPts         = 200;
+    double E[nPts];
+    double f[nPts];
+
+    // create a rappture library from the file filePath
+    lib = Rappture::Library(argv[1]);
+
+    if (lib.error() != 0) {
+        // cannot open file or out of memory
+        fprintf(stderr, lib.traceback());
+        exit(lib.error());
+    }
+
+    Rappture::connect(lib,"temperature",&T);
+    Rappture::connect(lib,"Ef",&Ef);
+
+    if (lib.error() != 0) {
+        // there were errors while retrieving input data values
+        // dump the tracepack
+        fprintf(stderr, lib.traceback());
+        exit(lib.error());
+    }
+
+    kT = 8.61734e-5 * T->value("K");
+    Emin = Ef->value("eV") - 10*kT;
+    Emax = Ef->value("eV") + 10*kT;
+
+    dE = (1.0/nPts)*(Emax-Emin);
+
+    E = Emin;
+    for (size_t idx = 0; idx < nPts; idx++) {
+        E = E + dE;
+        f = 1.0/(1.0 + exp((E - Ef)/kT));
+        fArr[idx] = f;
+        EArr[idx] = E;
+        rpUtilsProgress((int)((E-Emin)/(Emax-Emin)*100),"Iterating");
+    }
+
+    const char *curveLabel = "Fermi-Dirac Curve"
+    const char *curveDesc = "Plot of Fermi-Dirac Calculation";
+
+    // do it the easy way,
+    // create a plot to add to the library
+    // plot is registered with lib upon object creation
+    // p1->add(nPts,xArr,yArr,format,curveLabel,curveDesc);
+
+    Rappture::Plot p1(lib);
+    p1.add(nPts,fArr,EArr,"",curveLabel,curveDesc);
+    p1.propstr("xlabel","Fermi-Dirac Factor");
+    p1.propstr("ylabel","Energy");
+    p1.propstr("yunits","eV");
+
+    lib.result();
+
+    return 0;
+}
Index: /trunk/examples/objects/curve/curve.cc
===================================================================
--- /trunk/examples/objects/curve/curve.cc	(revision 1559)
+++ /trunk/examples/objects/curve/curve.cc	(revision 1560)
@@ -1,4 +1,7 @@
 #include <iostream>
 #include "RpCurve.h"
+
+size_t indent = 0;
+size_t tabstop = 4;
 
 int test(
@@ -34,5 +37,5 @@
     }
 
-    std::cout << "xml: " << n->xml() << std::endl;
+    std::cout << "xml: " << n->xml(indent,tabstop) << std::endl;
     return 0;
 }
Index: /trunk/examples/objects/histogram/histogram.cc
===================================================================
--- /trunk/examples/objects/histogram/histogram.cc	(revision 1559)
+++ /trunk/examples/objects/histogram/histogram.cc	(revision 1560)
@@ -36,8 +36,10 @@
     h3->yaxis("ylabel3","ydesc3","yunits3");
 
+    size_t indent = 0;
+    size_t tabstop = 4;
 
-    std::printf("xml: %s\n",h1->xml());
-    std::printf("xml: %s\n",h2->xml());
-    std::printf("xml: %s\n",h3->xml());
+    std::printf("xml: %s\n",h1->xml(indent,tabstop));
+    std::printf("xml: %s\n",h2->xml(indent,tabstop));
+    std::printf("xml: %s\n",h3->xml(indent,tabstop));
 
     return 0;
Index: /trunk/examples/objects/number/Makefile.in
===================================================================
--- /trunk/examples/objects/number/Makefile.in	(revision 1559)
+++ /trunk/examples/objects/number/Makefile.in	(revision 1560)
@@ -34,4 +34,5 @@
 FILES   = \
 		$(srcdir)/number.cc \
+		$(srcdir)/number_1_0_in.xml \
 		Makefile
 
Index: /trunk/examples/objects/number/number.cc
===================================================================
--- /trunk/examples/objects/number/number.cc	(revision 1559)
+++ /trunk/examples/objects/number/number.cc	(revision 1560)
@@ -1,8 +1,15 @@
 #include <iostream>
+#include <errno.h>
+#include <fstream>
+#include <sys/stat.h>
 #include "RpNumber.h"
+
+size_t indent = 0;
+size_t tabstop = 4;
 
 int
 printNumber(Rappture::Number *n)
 {
+    std::cout << "name: " << n->name() << std::endl;
     std::cout << "path: " << n->path() << std::endl;
     std::cout << "label: " << n->label() << std::endl;
@@ -13,22 +20,201 @@
     std::cout << "max: " << n->max() << std::endl;
     std::cout << "units: " << n->units() << std::endl;
-    std::cout << "xml: " << n->xml() << std::endl;
-    return 0;
+    std::cout << "xml:\n" << n->xml(indent,tabstop) << std::endl;
+    return 0;
+}
+
+int testStringVal(
+    const char *testname,
+    const char *desc,
+    const char *expected,
+    const char *received)
+{
+    if ((!expected && received) ||
+        (expected && !received) ||
+        (expected && received && strcmp(expected,received) != 0)) {
+        printf("Error: %s\n", testname);
+        printf("\t%s\n", desc);
+        printf("\texpected \"%s\"\n",expected);
+        printf("\treceived \"%s\"\n",received);
+        return 1;
+    }
+    return 0;
+}
+
+int testDoubleVal(
+    const char *testname,
+    const char *desc,
+    double expected,
+    double received)
+{
+    if (expected != received) {
+        printf("Error: %s\n", testname);
+        printf("\t%s\n", desc);
+        printf("\texpected \"%g\"\n",expected);
+        printf("\treceived \"%g\"\n",received);
+        return 1;
+    }
+    return 0;
+}
+
+size_t
+readFile (
+    const char *filePath,
+    const char **buf)
+{
+    if (buf == NULL) {
+        fprintf(stderr,"buf is NULL while opening file \"%s\"", filePath);
+        return 0;
+    }
+
+    FILE *f;
+    f = fopen(filePath, "rb");
+    if (f == NULL) {
+        fprintf(stderr,"can't open \"%s\": %s", filePath, strerror(errno));
+        return 0;
+    }
+    struct stat stat;
+    if (fstat(fileno(f), &stat) < 0) {
+        fprintf(stderr,"can't stat \"%s\": %s", filePath, strerror(errno));
+        return 0;
+    }
+    off_t size;
+    size = stat.st_size;
+    char* memblock;
+    memblock = new char [size+1];
+    if (memblock == NULL) {
+        fprintf(stderr,"can't allocate %zu bytes for file \"%s\": %s",
+            size, filePath, strerror(errno));
+        fclose(f);
+        return 0;
+    }
+
+    size_t nRead;
+    nRead = fread(memblock, sizeof(char), size, f);
+    fclose(f);
+
+    if (nRead != (size_t)size) {
+        fprintf(stderr,"can't read %zu bytes from \"%s\": %s", size, filePath,
+            strerror(errno));
+        return 0;
+    }
+
+    memblock[size] = '\0';
+    *buf = memblock;
+    return nRead;
+}
+int number_0_0 ()
+{
+    const char *testdesc = "test number full constructor";
+    const char *testname = "number_0_0";
+    int retVal = 0;
+
+    const char *name = "temp";
+    const char *units = "K";
+    double def = 300;
+    double min = 0;
+    double max = 1000;
+    const char *label = "mylabel";
+    const char *desc = "mydesc";
+
+    Rappture::Number *n = NULL;
+
+    n = new Rappture::Number(name,units,def,min,max,label,desc);
+
+    if (n == NULL) {
+        printf("Error: %s\n", testname);
+        printf("\t%s\n", testdesc);
+        printf("\terror creating number object\n");
+        retVal = 1;
+    }
+
+    retVal |= testStringVal(testname,testdesc,name,n->name());
+    retVal |= testStringVal(testname,testdesc,units,n->units());
+    retVal |= testDoubleVal(testname,testdesc,def,n->def());
+    retVal |= testDoubleVal(testname,testdesc,min,n->min());
+    retVal |= testDoubleVal(testname,testdesc,max,n->max());
+    retVal |= testStringVal(testname,testdesc,label,n->label());
+    retVal |= testStringVal(testname,testdesc,desc,n->desc());
+
+    if (n != NULL) {
+        delete n;
+    }
+
+    return retVal;
+}
+
+int number_0_1 ()
+{
+    const char *testdesc = "test number constuctor";
+    const char *testname = "number_0_0";
+    int retVal = 0;
+
+    const char *name = "eV";
+    const char *units = "eV";
+    double def = 1.4;
+
+    Rappture::Number *n = NULL;
+
+    n = new Rappture::Number(name,units,def);
+
+    if (n == NULL) {
+        printf("Error: %s\n", testname);
+        printf("\t%s\n", testdesc);
+        printf("\terror creating number object\n");
+        retVal = 1;
+    }
+
+    retVal |= testStringVal(testname,testdesc,name,n->name());
+    retVal |= testStringVal(testname,testdesc,units,n->units());
+    retVal |= testDoubleVal(testname,testdesc,def,n->def());
+
+    if (n != NULL) {
+        delete n;
+    }
+
+    return retVal;
+}
+
+int number_1_0 ()
+{
+    const char *testdesc = "test constructing number from xml";
+    const char *testname = "number_1_0";
+    const char *filePath = "number_1_0_in.xml";
+    int retVal = 0;
+
+    const char *buf = NULL;
+    readFile(filePath,&buf);
+
+    const char *name = "Ef";
+    const char *units = "eV";
+    double def = 0;
+    double cur = 5;
+    double min = -10;
+    double max = 10;
+    const char *label = "Fermi Level";
+    const char *desc = "Energy at center of distribution.";
+
+    Rappture::Number n;
+
+    n.xml(buf);
+
+    retVal |= testStringVal(testname,testdesc,name,n.name());
+    retVal |= testStringVal(testname,testdesc,units,n.units());
+    retVal |= testDoubleVal(testname,testdesc,def,n.def());
+    retVal |= testDoubleVal(testname,testdesc,cur,n.cur());
+    retVal |= testDoubleVal(testname,testdesc,min,n.min());
+    retVal |= testDoubleVal(testname,testdesc,max,n.max());
+    retVal |= testStringVal(testname,testdesc,label,n.label());
+    retVal |= testStringVal(testname,testdesc,desc,n.desc());
+
+    return retVal;
 }
 
 int main()
 {
-    Rappture::Number *n = NULL;
-
-    n = new Rappture::Number("input.number(temperature)","K",300,
-                             0,1000,"mylabel","mydesc");
-
-    printNumber(n);
-
-    Rappture::Number n1("input.number(eV)","eV",1.4);
-    printNumber(&n1);
-
-    delete n;
-
-    return 0;
-}
+    number_0_0();
+    number_0_1();
+    number_1_0();
+
+    return 0;
+}
Index: /trunk/examples/objects/number/number_1_0_in.xml
===================================================================
--- /trunk/examples/objects/number/number_1_0_in.xml	(revision 1560)
+++ /trunk/examples/objects/number/number_1_0_in.xml	(revision 1560)
@@ -0,0 +1,24 @@
+<?xml version="1.0"?>
+<number id="Ef">
+    <about>
+        <label>Fermi Level</label>
+        <description>Energy at center of distribution.</description>
+    </about>
+    <units>eV</units>
+    <min>-10eV</min>
+    <max>10eV</max>
+    <default>0eV</default>
+    <current>5eV</current>
+    <preset>
+        <value>300K</value>
+        <label>300K (room temperature)</label>
+    </preset>
+    <preset>
+        <value>77K</value>
+        <label>77K (liquid nitrogen)</label>
+    </preset>
+    <preset>
+        <value>4.2K</value>
+        <label>4.2K (liquid helium)</label>
+    </preset>
+</number>
Index: /trunk/examples/objects/path/path.cc
===================================================================
--- /trunk/examples/objects/path/path.cc	(revision 1559)
+++ /trunk/examples/objects/path/path.cc	(revision 1560)
@@ -8,5 +8,7 @@
     const char *received)
 {
-    if (strcmp(expected,received) != 0) {
+    if ((!expected && received) ||
+        (expected && !received) ||
+        (expected && received && strcmp(expected,received) != 0)) {
         printf("Error: %s\n", testname);
         printf("\t%s\n", desc);
@@ -114,5 +116,5 @@
 
     const char *path = "input.group(tabs).number(mynum).current";
-    const char *expected = "";
+    const char *expected = NULL;
     const char *received = NULL;
 
@@ -773,4 +775,11 @@
 // FIXME: add test for parent get/set functions
 // FIXME: add test for path get/set functions
+// FIXME: add test for changing the curr location
+//        using first,last,next,prev and checking
+//        comp, type, parent,id fxns
+// FIXME: add test for numbered paths
+//        input.number2
+//        input.number2(eee)
+//        input.number(eee)2
 
 int main()
Index: /trunk/examples/objects/plot/plot.cc
===================================================================
--- /trunk/examples/objects/plot/plot.cc	(revision 1559)
+++ /trunk/examples/objects/plot/plot.cc	(revision 1560)
@@ -41,5 +41,8 @@
     std::printf("curveCnt = %zu\n",curveCnt);
 
-    std::printf("xml: %s\n",p1->xml());
+    size_t indent = 0;
+    size_t tabstop = 4;
+
+    std::printf("xml: %s\n",p1->xml(indent,tabstop));
 
 /*
Index: /trunk/examples/objects/scatter/scatter.cc
===================================================================
--- /trunk/examples/objects/scatter/scatter.cc	(revision 1559)
+++ /trunk/examples/objects/scatter/scatter.cc	(revision 1560)
@@ -41,5 +41,7 @@
     std::printf("curveCnt = %zu\n",curveCnt);
 
-    std::printf("xml: %s\n",p1->xml());
+    size_t indent = 0;
+    size_t tabstop = 4;
+    std::printf("xml: %s\n",p1->xml(indent,tabstop));
 
 /*
Index: /trunk/examples/objects/tree/tree.c
===================================================================
--- /trunk/examples/objects/tree/tree.c	(revision 1559)
+++ /trunk/examples/objects/tree/tree.c	(revision 1560)
@@ -14,5 +14,5 @@
     Rp_Tree t;
 
-    Rp_TreeCreate(treeName,t);
+    Rp_TreeCreate(treeName,&t);
     received = Rp_TreeName(t);
 
@@ -28,8 +28,183 @@
 }
 
+int tree_1_0 ()
+{
+    const char *desc = "test creation of tree node";
+    const char *testname = "tree_1_0";
+
+    const char *treeName = "mytree";
+    const char *nodeName = "mynode";
+    const char *expected = "mynode";
+    const char *received = NULL;
+
+    Rp_Tree t;
+    Rp_TreeNode n = NULL;
+
+    Rp_TreeCreate(treeName,&t);
+    n = Rp_TreeCreateNode(t, Rp_TreeRootNode(t), nodeName, 0);
+    received = Rp_TreeNodeLabel(n);
+
+    if (strcmp(expected,received) != 0) {
+        printf("Error: %s\n", testname);
+        printf("\t%s\n", desc);
+        printf("\texpected \"%s\"\n",expected);
+        printf("\treceived \"%s\"\n",received);
+        return 1;
+    }
+
+    return 0;
+}
+
+int tree_2_0 ()
+{
+    const char *desc = "test creation of tree node with single child";
+    const char *testname = "tree_2_0";
+
+    const char *treeName = "mytree";
+    const char *parentNodeName = "myparentnode";
+    const char *childNodeName = "mychildnode";
+    const char *expected = "mychildnode";
+    const char *received = NULL;
+
+    Rp_Tree t;
+    Rp_TreeNode parent = NULL;
+    Rp_TreeNode child = NULL;
+
+    Rp_TreeCreate(treeName,&t);
+    parent = Rp_TreeCreateNode(t, Rp_TreeRootNode(t), parentNodeName, 0);
+    child = Rp_TreeCreateNode(t, parent, childNodeName, 0);
+    received = Rp_TreeNodeLabel(child);
+
+    if (strcmp(expected,received) != 0) {
+        printf("Error: %s\n", testname);
+        printf("\t%s\n", desc);
+        printf("\texpected \"%s\"\n",expected);
+        printf("\treceived \"%s\"\n",received);
+        return 1;
+    }
+
+    return 0;
+}
+
+int tree_2_1 ()
+{
+    const char *desc = "test creation of tree node with multiple children";
+    const char *testname = "tree_2_1";
+
+    const char *treeName = "mytree";
+    const char *parentNodeName = "myparentnode";
+    size_t expected = 5;
+    size_t received = 0;
+
+    Rp_Tree t;
+    Rp_TreeNode parent = NULL;
+
+    Rp_TreeCreate(treeName,&t);
+    parent = Rp_TreeCreateNode(t, Rp_TreeRootNode(t), parentNodeName, 0);
+
+    Rp_TreeCreateNode(t, parent, "child1", 0);
+    Rp_TreeCreateNode(t, parent, "child2", 0);
+    Rp_TreeCreateNode(t, parent, "child3", 0);
+    Rp_TreeCreateNode(t, parent, "child4", 0);
+    Rp_TreeCreateNode(t, parent, "child5", 0);
+
+    received = Rp_TreeNodeDegree(parent);
+
+    if (expected != received) {
+        printf("Error: %s\n", testname);
+        printf("\t%s\n", desc);
+        printf("\texpected \"%zu\"\n",expected);
+        printf("\treceived \"%zu\"\n",received);
+        return 1;
+    }
+
+    return 0;
+}
+
+int tree_2_2 ()
+{
+    const char *desc = "test search for child node";
+    const char *testname = "tree_2_2";
+
+    const char *treeName = "mytree";
+    const char *parentNodeName = "myparentnode";
+    const char *childNodeName = "mychildnode";
+    const char *expected = "mychildnode";
+    const char *received = NULL;
+
+    Rp_Tree t;
+    Rp_TreeNode parent = NULL;
+    Rp_TreeNode foundChild = NULL;
+
+    Rp_TreeCreate(treeName,&t);
+    parent = Rp_TreeCreateNode(t, Rp_TreeRootNode(t), parentNodeName, 0);
+
+    Rp_TreeCreateNode(t, parent, "child1", 0);
+    Rp_TreeCreateNode(t, parent, "child2", 0);
+    Rp_TreeCreateNode(t, parent, "child3", 0);
+    Rp_TreeCreateNode(t, parent, childNodeName, 0);
+    Rp_TreeCreateNode(t, parent, "child4", 0);
+    Rp_TreeCreateNode(t, parent, "child5", 0);
+
+    foundChild = Rp_TreeFindChild(parent,childNodeName);
+    received = Rp_TreeNodeLabel(foundChild);
+
+    if (strcmp(expected,received) != 0) {
+        printf("Error: %s\n", testname);
+        printf("\t%s\n", desc);
+        printf("\texpected \"%s\"\n",expected);
+        printf("\treceived \"%s\"\n",received);
+        return 1;
+    }
+
+    return 0;
+}
+
+int tree_3_0 ()
+{
+    const char *desc = "test adding node with string value";
+    const char *testname = "tree_3_0";
+
+    const char *treeName = "mytree";
+    const char *parentNodeName = "myparentnode";
+    const char *childNodeName = "mychildnode";
+    const char *childNodeValue = "quick brown fox";
+    const char *expected = "quick brown fox1";
+    const char *received = NULL;
+
+    Rp_Tree t;
+    Rp_TreeNode parent = NULL;
+    Rp_TreeNode child = NULL;
+
+    Rp_TreeCreate(treeName,&t);
+    parent = Rp_TreeCreateNode(t, Rp_TreeRootNode(t), parentNodeName, 0);
+
+    child = Rp_TreeCreateNode(t, parent, childNodeName, 0);
+    Rp_TreeSetValue(t,child,"value",(void *)childNodeValue);
+
+    Rp_TreeGetValue(t,child,"value",(void **)&received);
+
+    if (strcmp(expected,received) != 0) {
+        printf("Error: %s\n", testname);
+        printf("\t%s\n", desc);
+        printf("\texpected \"%s\"\n",expected);
+        printf("\treceived \"%s\"\n",received);
+        return 1;
+    }
+
+    return 0;
+}
+
 int main()
 {
     tree_0_0();
-
-    return 0;
-}
+    tree_1_0();
+    tree_2_0();
+    tree_2_1();
+    tree_2_2();
+    tree_3_0();
+
+    // add test case where two children have the same name but different ids
+
+    return 0;
+}
Index: /trunk/examples/objects/xmlparser/Makefile.in
===================================================================
--- /trunk/examples/objects/xmlparser/Makefile.in	(revision 1559)
+++ /trunk/examples/objects/xmlparser/Makefile.in	(revision 1560)
@@ -34,4 +34,7 @@
 FILES   = \
 		$(srcdir)/xmlparser.cc \
+		$(srcdir)/xmlparser_1_0_in.xml \
+		$(srcdir)/xmlparser_1_0_out.xml \
+		$(srcdir)/xmlparser_2_0_in.xml \
 		$(srcdir)/tool.xml \
 		Makefile
Index: /trunk/examples/objects/xmlparser/xmlparser.cc
===================================================================
--- /trunk/examples/objects/xmlparser/xmlparser.cc	(revision 1559)
+++ /trunk/examples/objects/xmlparser/xmlparser.cc	(revision 1560)
@@ -1,199 +1,311 @@
-#include <stdio.h>
-#include <expat.h>
-#include <string.h>
-#include "RpInt.h"
-#include "RpChain.h"
-#include "RpPath.h"
-#include "RpNumber.h"
-
-#define BUFFSIZE        8192
-
-char Buff[BUFFSIZE];
-
-typedef struct {
-    int skip;
-    int depth;
-    Rappture::Path *path;
-    Rp_Chain *c;
-    void *lastObj;
-    int lastObjType;
-    Rappture::Object *v;
-} Parseinfo;
-
-void
-init_info(Parseinfo *info) {
-    info->skip = 0;
-    info->depth = 1;
-    info->path = new Rappture::Path();
-    info->c = Rp_ChainCreate();
-    info->lastObj = NULL;
-    info->lastObjType = 0;
-    info->v = NULL;
-}
-
-int
-should_skip(Parseinfo *inf, const char *el, const char **attr) {
-    int skip = 0;
-
-    if ( (*el == 's') && (strcmp("string",el) == 0) ) {
-        skip = 1;
-    }
-
-    return skip;
-}
-
-static void XMLCALL
-start(void *data, const char *el, const char **attr)
-{
-    Parseinfo *inf = (Parseinfo *) data;
-
-    if ( (*el == 'i') && (strcmp("input",el) == 0) ) {
-        inf->path->add(el);
-    } else if ( (*el == 'n') && (strcmp("number",el) == 0) ) {
-        inf->path->add(el);
-        // null units kills number
-        // Rappture::Number *n = new Rappture::Number(inf->path->path(NULL),NULL,0.0);
-        Rappture::Number *n = new Rappture::Number(inf->path->path(),"",0.0);
-        Rp_ChainAppend(inf->c,n);
-        inf->v = n;
-    } else {
-        // add the tags to the hash table of the last object we created.
-        // this means new objects must be declared here,
-        // or they will become part of the last recognized object
-        // this could lead to major problems.
-        // we have no way to ignore stuff we don't recognize
-
-        inf->path->add(el);
-        if (inf->v) {
-            // inf->v->property(el,);
-        }
-    }
-
-    inf->depth++;
-}
-
-static void XMLCALL
-end(void *data, const char *el)
-{
-    Parseinfo *inf = (Parseinfo *) data;
-    inf->path->del();
-    inf->depth--;
-    // pop object off the end of the inf->c chain
-    // add object to the tree object
-}
-
-void
-rawstart(void *data, const char *el, const char **attr) {
-    Parseinfo *inf = (Parseinfo *) data;
-
-    if (! inf->skip) {
-        if (should_skip(inf, el, attr)) {
-            inf->skip = inf->depth;
-        }
-        else {
-            start(inf, el, attr);     /* This does rest of start handling */
-        }
-    }
-
-    inf->depth++;
-}  /* End of rawstart */
-
-void
-rawend(void *data, const char *el) {
-    Parseinfo *inf = (Parseinfo *) data;
-
-    inf->depth--;
-
-    if (! inf->skip) {
-        end(inf, el);              /* This does rest of end handling */
-    }
-
-    if (inf->skip == inf->depth) {
-        inf->skip = 0;
-    }
-}  /* End rawend */
-
-/*
-void
-char_handler(void* data, XML_Char const* s, int len)
-{
-    int total = 0;
-    int total_old = 0;
-    scew_element* current = NULL;
-    Parseinfo *inf = (Parseinfo *) data;
-
-    if (inf == NULL) {
-        return;
-    }
-
-    if (inf->v == NULL)
-    {
-        return;
-    }
-
-    if (current->contents != NULL)
-    {
-        total_old = scew_strlen(current->contents);
-    }
-    total = (total_old + len + 1) * sizeof(XML_Char);
-    current->contents = (XML_Char*) realloc(current->contents, total);
-
-    if (total_old == 0)
-    {
-        current->contents[0] = '\0';
-    }
-
-    scew_strncat(current->contents, s, len);
-}
-*/
-
-
-int
-main(int argc, char *argv[])
-{
-    Parseinfo info;
-    XML_Parser p = XML_ParserCreate(NULL);
-    if (! p) {
-        fprintf(stderr, "Couldn't allocate memory for parser\n");
-        exit(-1);
-    }
-
-    init_info(&info);
-    XML_SetUserData(p,&info);
-
-    XML_SetElementHandler(p, rawstart, rawend);
-    //XML_SetDefaultHandler(p, char_handler);
-
-    for (;;) {
-        int done;
-        int len;
-
-        len = fread(Buff, 1, BUFFSIZE, stdin);
-        if (ferror(stdin)) {
-            fprintf(stderr, "Read error\n");
-            exit(-1);
-        }
-        done = feof(stdin);
-
-        if (XML_Parse(p, Buff, len, done) == XML_STATUS_ERROR) {
-            fprintf(stderr, "Parse error at line %lu:\n%s\n",
-                    XML_GetCurrentLineNumber(p),
-                    XML_ErrorString(XML_GetErrorCode(p)));
-            exit(-1);
-        }
-
-        if (done) {
-            break;
-        }
-    }
-
-    Rp_ChainLink *lv = NULL;
-    Rappture::Number *n = NULL;
-    lv = Rp_ChainFirstLink(info.c);
-    while (lv) {
-        n = (Rappture::Number *) Rp_ChainGetValue(lv);
-        printf("%s\n",n->xml());
-        lv = Rp_ChainNextLink(lv);
-    }
+#include <iostream>
+#include <errno.h>
+#include <fstream>
+#include <sys/stat.h>
+#include "RpParserXML.h"
+
+size_t
+readFile (
+    const char *filePath,
+    const char **buf)
+{
+    if (buf == NULL) {
+        fprintf(stderr,"buf is NULL while opening file \"%s\"", filePath);
+        return 0;
+    }
+
+    FILE *f;
+    f = fopen(filePath, "rb");
+    if (f == NULL) {
+        fprintf(stderr,"can't open \"%s\": %s", filePath, strerror(errno));
+        return 0;
+    }
+    struct stat stat;
+    if (fstat(fileno(f), &stat) < 0) {
+        fprintf(stderr,"can't stat \"%s\": %s", filePath, strerror(errno));
+        return 0;
+    }
+    off_t size;
+    size = stat.st_size;
+    char* memblock;
+    memblock = new char [size+1];
+    if (memblock == NULL) {
+        fprintf(stderr,"can't allocate %zu bytes for file \"%s\": %s",
+            size, filePath, strerror(errno));
+        fclose(f);
+        return 0;
+    }
+
+    size_t nRead;
+    nRead = fread(memblock, sizeof(char), size, f);
+    fclose(f);
+
+    if (nRead != (size_t)size) {
+        fprintf(stderr,"can't read %zu bytes from \"%s\": %s", size, filePath,
+            strerror(errno));
+        return 0;
+    }
+
+    memblock[size] = '\0';
+    *buf = memblock;
+    return nRead;
+}
+
+int xmlparser_0_0 ()
+{
+    const char *desc = "test creating xml parser";
+    const char *testname = "xmlparser_0_0";
+    int retVal = 0;
+
+    const char *expected = "initialized ParserXml Object";
+    const char *received = NULL;
+
+    Rp_ParserXml *p = NULL;
+
+    p = Rp_ParserXmlCreate();
+
+    if (p == NULL) {
+        printf("Error: %s\n", testname);
+        printf("\t%s\n", desc);
+        printf("\texpected \"%s\"\n",expected);
+        printf("\treceived \"%s\"\n",received);
+        retVal = 1;
+    }
+
+    if (p) {
+        Rp_ParserXmlDestroy(&p);
+    }
+
+    return retVal;
+}
+
+int xmlparser_1_0 ()
+{
+    const char *desc = "test sending xml text to xml parser";
+    const char *testname = "xmlparser_1_0";
+    const char *infile = "xmlparser_1_0_in.xml";
+    const char *outfile = "xmlparser_1_0_out.xml";
+    int retVal = 0;
+
+    const char *xmltext = NULL;
+    const char *expected = NULL;
+
+    readFile(infile,&xmltext);
+    readFile(outfile,&expected);
+
+    const char *received = NULL;
+
+    Rp_ParserXml *p = NULL;
+
+    p = Rp_ParserXmlCreate();
+
+    Rp_ParserXmlParse(p, xmltext);
+
+    received = Rp_ParserXmlXml(p);
+
+
+    if (strcmp(expected,received) != 0) {
+        printf("Error: %s\n", testname);
+        printf("\t%s\n", desc);
+        printf("\texpected %zu bytes: \"%s\"\n",strlen(expected), expected);
+        printf("\treceived %zu bytes: \"%s\"\n",strlen(received), received);
+        retVal = 1;
+    }
+
+    if (p) {
+        Rp_ParserXmlDestroy(&p);
+    }
+
+    return retVal;
+}
+
+
+int xmlparser_2_0 ()
+{
+    const char *desc = "test printing xml as path/val combos";
+    const char *testname = "xmlparser_2_0";
+    const char *infile = "xmlparser_2_0_in.xml";
+    int retVal = 0;
+
+    const char *xmltext = NULL;
+
+    readFile(infile,&xmltext);
+
+    const char *expected = "\
+run.tool.about Press Simulate to view results.\n\
+run.tool.command tclsh @tool/fermi.tcl @driver\n\
+run.input.number(Ef).about.label Fermi Level\n\
+run.input.number(Ef).about.description Energy at center of distribution.\n\
+run.input.number(Ef).units eV\n\
+run.input.number(Ef).min -10eV\n\
+run.input.number(Ef).max 10eV\n\
+run.input.number(Ef).default 0eV\n\
+run.input.number(Ef).current 0eV\n";
+
+    const char *received = NULL;
+
+    Rp_ParserXml *p = NULL;
+
+    p = Rp_ParserXmlCreate();
+
+    Rp_ParserXmlParse(p, xmltext);
+
+    received = Rp_ParserXmlPathVal(p);
+
+
+    if (strcmp(expected,received) != 0) {
+        printf("Error: %s\n", testname);
+        printf("\t%s\n", desc);
+        printf("\texpected %zu bytes: \"%s\"\n",strlen(expected), expected);
+        printf("\treceived %zu bytes: \"%s\"\n",strlen(received), received);
+        retVal = 1;
+    }
+
+    if (p) {
+        Rp_ParserXmlDestroy(&p);
+    }
+
+    return retVal;
+}
+
+int xmlparser_3_0 ()
+{
+    const char *desc = "test getting xml value";
+    const char *testname = "xmlparser_3_0";
+    const char *infile = "xmlparser_2_0_in.xml";
+    int retVal = 0;
+
+    const char *xmltext = NULL;
+
+    readFile(infile,&xmltext);
+
+    const char *expected = "0eV";
+
+    const char *received = NULL;
+
+    Rp_ParserXml *p = NULL;
+
+    p = Rp_ParserXmlCreate();
+
+    Rp_ParserXmlParse(p, xmltext);
+
+    received = Rp_ParserXmlGet(p,"input.number(Ef).current");
+
+
+    if (strcmp(expected,received) != 0) {
+        printf("Error: %s\n", testname);
+        printf("\t%s\n", desc);
+        printf("\texpected %zu bytes: \"%s\"\n",strlen(expected), expected);
+        printf("\treceived %zu bytes: \"%s\"\n",strlen(received), received);
+        retVal = 1;
+    }
+
+    if (p) {
+        Rp_ParserXmlDestroy(&p);
+    }
+
+    return retVal;
+}
+
+int xmlparser_4_0 ()
+{
+    const char *desc = "test putting xml value";
+    const char *testname = "xmlparser_4_0";
+    const char *infile = "xmlparser_2_0_in.xml";
+    int retVal = 0;
+
+    const char *xmltext = NULL;
+
+    readFile(infile,&xmltext);
+
+    const char *expected = "hi mom";
+
+    const char *received = NULL;
+
+    Rp_ParserXml *p = NULL;
+
+    p = Rp_ParserXmlCreate();
+
+    Rp_ParserXmlParse(p, xmltext);
+
+    Rp_ParserXmlPut(p,"input.number(gg).current","hi mom",0);
+    received = Rp_ParserXmlGet(p,"input.number(gg).current");
+
+    if (strcmp(expected,received) != 0) {
+        printf("Error: %s\n", testname);
+        printf("\t%s\n", desc);
+        printf("\texpected %zu bytes: \"%s\"\n",strlen(expected), expected);
+        printf("\treceived %zu bytes: \"%s\"\n",strlen(received), received);
+        retVal = 1;
+    }
+
+    if (p) {
+        Rp_ParserXmlDestroy(&p);
+    }
+
+    return retVal;
+}
+
+int xmlparser_5_0 ()
+{
+    const char *desc = "test printing xml with degrees of presets";
+    const char *testname = "xmlparser_5_0";
+    const char *infile = "xmlparser_5_0_in.xml";
+    int retVal = 0;
+
+    const char *xmltext = NULL;
+
+    readFile(infile,&xmltext);
+
+    const char *expected = "\
+run.tool.about Press Simulate to view results.\n\
+run.tool.command tclsh @tool/fermi.tcl @driver\n\
+run.input.number(Ef).about.label Fermi Level\n\
+run.input.number(Ef).about.description Energy at center of distribution.\n\
+run.input.number(Ef).units eV\n\
+run.input.number(Ef).min -10eV\n\
+run.input.number(Ef).max 10eV\n\
+run.input.number(Ef).default 0eV\n\
+run.input.number(Ef).current 0eV\n";
+
+    const char *received = NULL;
+
+    Rp_ParserXml *p = NULL;
+
+    p = Rp_ParserXmlCreate();
+
+    Rp_ParserXmlParse(p, xmltext);
+
+    received = Rp_ParserXmlPathVal(p);
+
+
+    if (strcmp(expected,received) != 0) {
+        printf("Error: %s\n", testname);
+        printf("\t%s\n", desc);
+        printf("\texpected %zu bytes: \"%s\"\n",strlen(expected), expected);
+        printf("\treceived %zu bytes: \"%s\"\n",strlen(received), received);
+        retVal = 1;
+    }
+
+    if (p) {
+        Rp_ParserXmlDestroy(&p);
+    }
+
+    return retVal;
+}
+
+// FIXME: test what happens when parser sees self closing tag <tag/>
+// FIXME: test get function
+// FIXME: test put function
+// FIXME: look into why Rp_ParserXmlPathVal hits some nodes twice in gdb
+
+int main()
+{
+    xmlparser_0_0();
+    xmlparser_1_0();
+    xmlparser_2_0();
+    xmlparser_3_0();
+    xmlparser_4_0();
+    xmlparser_5_0();
 
     return 0;
Index: /trunk/examples/objects/xmlparser/xmlparser_1_0_in.xml
===================================================================
--- /trunk/examples/objects/xmlparser/xmlparser_1_0_in.xml	(revision 1560)
+++ /trunk/examples/objects/xmlparser/xmlparser_1_0_in.xml	(revision 1560)
@@ -0,0 +1,20 @@
+<?xml version="1.0"?>
+<run>
+    <tool>
+        <about>Press Simulate to view results.</about>
+        <command>tclsh @tool/fermi.tcl @driver</command>
+    </tool>
+    <input>
+        <number id="Ef">
+            <about>
+                <label>Fermi Level</label>
+                <description>Energy at center of distribution.</description>
+            </about>
+            <units>eV</units>
+            <min>-10eV</min>
+            <max>10eV</max>
+            <default>0eV</default>
+            <current>  0eV   </current>
+        </number>
+    </input>
+</run>
Index: /trunk/examples/objects/xmlparser/xmlparser_1_0_out.xml
===================================================================
--- /trunk/examples/objects/xmlparser/xmlparser_1_0_out.xml	(revision 1560)
+++ /trunk/examples/objects/xmlparser/xmlparser_1_0_out.xml	(revision 1560)
@@ -0,0 +1,20 @@
+<?xml version="1.0"?>
+<run>
+    <tool>
+        <about>Press Simulate to view results.</about>
+        <command>tclsh @tool/fermi.tcl @driver</command>
+    </tool>
+    <input>
+        <number id="Ef">
+            <about>
+                <label>Fermi Level</label>
+                <description>Energy at center of distribution.</description>
+            </about>
+            <units>eV</units>
+            <min>-10eV</min>
+            <max>10eV</max>
+            <default>0eV</default>
+            <current>0eV</current>
+        </number>
+    </input>
+</run>
Index: /trunk/examples/objects/xmlparser/xmlparser_2_0_in.xml
===================================================================
--- /trunk/examples/objects/xmlparser/xmlparser_2_0_in.xml	(revision 1560)
+++ /trunk/examples/objects/xmlparser/xmlparser_2_0_in.xml	(revision 1560)
@@ -0,0 +1,20 @@
+<?xml version="1.0"?>
+<run>
+    <tool>
+        <about>Press Simulate to view results.</about>
+        <command>tclsh @tool/fermi.tcl @driver</command>
+    </tool>
+    <input>
+        <number id="Ef">
+            <about>
+                <label>Fermi Level</label>
+                <description>Energy at center of distribution.</description>
+            </about>
+            <units>eV</units>
+            <min>-10eV</min>
+            <max>10eV</max>
+            <default>0eV</default>
+            <current>0eV</current>
+        </number>
+    </input>
+</run>
Index: /trunk/examples/objects/xmlparser/xmlparser_3_0_in.xml
===================================================================
--- /trunk/examples/objects/xmlparser/xmlparser_3_0_in.xml	(revision 1560)
+++ /trunk/examples/objects/xmlparser/xmlparser_3_0_in.xml	(revision 1560)
@@ -0,0 +1,20 @@
+<?xml version="1.0"?>
+<run>
+    <tool>
+        <about>Press Simulate to view results.</about>
+        <command>tclsh @tool/fermi.tcl @driver</command>
+    </tool>
+    <input>
+        <number id="Ef">
+            <about>
+                <label>Fermi Level</label>
+                <description>Energy at center of distribution.</description>
+            </about>
+            <units>eV</units>
+            <min>-10eV</min>
+            <max>10eV</max>
+            <default>0eV</default>
+            <current>0eV</current>
+        </number>
+    </input>
+</run>
Index: /trunk/examples/objects/xmlparser/xmlparser_5_0_in.xml
===================================================================
--- /trunk/examples/objects/xmlparser/xmlparser_5_0_in.xml	(revision 1560)
+++ /trunk/examples/objects/xmlparser/xmlparser_5_0_in.xml	(revision 1560)
@@ -0,0 +1,32 @@
+<?xml version="1.0"?>
+<run>
+    <tool>
+        <about>Press Simulate to view results.</about>
+        <command>tclsh @tool/fermi.tcl @driver</command>
+    </tool>
+    <input>
+        <number id="Ef">
+            <about>
+                <label>Fermi Level</label>
+                <description>Energy at center of distribution.</description>
+            </about>
+            <units>eV</units>
+            <min>-10eV</min>
+            <max>10eV</max>
+            <default>0eV</default>
+            <current>0eV</current>
+            <preset>
+                <value>300K</value>
+                <label>300K (room temperature)</label>
+            </preset>
+            <preset>
+                <value>77K</value>
+                <label>77K (liquid nitrogen)</label>
+            </preset>
+            <preset>
+                <value>4.2K</value>
+                <label>4.2K (liquid helium)</label>
+            </preset>
+        </number>
+    </input>
+</run>
Index: /trunk/src/core/RpSimpleBuffer.h
===================================================================
--- /trunk/src/core/RpSimpleBuffer.h	(revision 1559)
+++ /trunk/src/core/RpSimpleBuffer.h	(revision 1560)
@@ -81,4 +81,5 @@
     SimpleBuffer     operator+(const SimpleBuffer& b) const;
     SimpleBuffer<T>& operator+=(const SimpleBuffer<T>& b);
+    T operator[](size_t offset);
     virtual ~SimpleBuffer();
 
@@ -241,4 +242,16 @@
 
 /**
+ * Operator []
+ * @param index into the buffer
+ */
+template<class T>
+T
+SimpleBuffer<T>::operator[](size_t idx)
+{
+    return (_buf+idx);
+}
+
+
+/**
  * Destructor
  */
Index: /trunk/src/objects/Makefile.in
===================================================================
--- /trunk/src/objects/Makefile.in	(revision 1559)
+++ /trunk/src/objects/Makefile.in	(revision 1560)
@@ -48,4 +48,7 @@
 LN              = ln -s
 
+#		RpDXReader.h \
+#		RpDXWriter.h \
+
 HEADERS = \
 		RpAccessor.h \
@@ -62,4 +65,5 @@
 		RpHistogram.h \
 		RpNumber.h \
+		RpParserXML.h \
 		RpPath.h \
 		RpPlot.h \
@@ -72,4 +76,7 @@
 LOCAL_HEADERS = \
 		RpHash.h
+
+#		RpDXReader.o \
+#		RpDXWriter.o \
 
 OBJS = \
@@ -86,4 +93,5 @@
 		RpHistogram.o \
 		RpNumber.o \
+		RpParserXML.o \
 		RpPath.o \
 		RpPlot.o \
Index: /trunk/src/objects/RpAccessor.h
===================================================================
--- /trunk/src/objects/RpAccessor.h	(revision 1559)
+++ /trunk/src/objects/RpAccessor.h	(revision 1560)
@@ -71,4 +71,8 @@
 Accessor<const char *>::operator() (const char *val)
 {
+    if (val == NULL) {
+        return;
+    }
+
     size_t len = strlen(val);
     char *tmp = new char[len+1];
Index: /trunk/src/objects/RpArray1D.cc
===================================================================
--- /trunk/src/objects/RpArray1D.cc	(revision 1559)
+++ /trunk/src/objects/RpArray1D.cc	(revision 1560)
@@ -180,5 +180,5 @@
 
 const char *
-Array1D::xml()
+Array1D::xml(size_t indent, size_t tabstop)
 {
     return "";
Index: /trunk/src/objects/RpArray1D.h
===================================================================
--- /trunk/src/objects/RpArray1D.h	(revision 1559)
+++ /trunk/src/objects/RpArray1D.h	(revision 1560)
@@ -41,5 +41,5 @@
     static const char type[];
 
-    const char *xml(void);
+    const char *xml(size_t indent, size_t tabstop);
     const int is(void) const;
 
Index: /trunk/src/objects/RpAxisMarker.cc
===================================================================
--- /trunk/src/objects/RpAxisMarker.cc	(revision 1559)
+++ /trunk/src/objects/RpAxisMarker.cc	(revision 1560)
@@ -139,14 +139,18 @@
 
 const char *
-AxisMarker::xml()
+AxisMarker::xml(size_t indent, size_t tabstop)
 {
+    size_t l1width = indent + tabstop;
+    const char *sp = "";
+
     _tmpBuf.clear();
 
     _tmpBuf.appendf(
-"        <marker>\n\
-            <at>%g</at>\n\
-            <label>%s</label>\n\
-            <style>%s</style>\n\
-        <marker>\n",_at,label(),_style);
+"%6$*4$s<marker>\n\
+%6$*5$s<at>%1$g</at>\n\
+%6$*5$s<label>%2$s</label>\n\
+%6$*5$s<style>%3$s</style>\n\
+%6$*4$s<marker>\n",
+        _at,label(),_style,indent,l1width,sp);
 
     _tmpBuf.append("\0",1);
Index: /trunk/src/objects/RpAxisMarker.h
===================================================================
--- /trunk/src/objects/RpAxisMarker.h	(revision 1559)
+++ /trunk/src/objects/RpAxisMarker.h	(revision 1560)
@@ -39,5 +39,5 @@
         double at (void) const;
 
-        const char *xml();
+        const char *xml(size_t indent, size_t tabstop);
         const int is(void) const;
 
Index: /trunk/src/objects/RpBoolean.cc
===================================================================
--- /trunk/src/objects/RpBoolean.cc	(revision 1559)
+++ /trunk/src/objects/RpBoolean.cc	(revision 1560)
@@ -65,6 +65,10 @@
 
 const char *
-Boolean::xml()
+Boolean::xml(size_t indent, size_t tabstop)
 {
+    size_t l1width = indent + tabstop;
+    size_t l2width = indent + (2*tabstop);
+    const char *sp = "";
+
     Path p(path());
     _tmpBuf.clear();
@@ -73,13 +77,13 @@
 
     _tmpBuf.appendf(
-"<boolean id=\"%s\">\n\
-    <about>\n\
-        <label>%s</label>\n\
-        <description>%s</description>\n\
-    </about>\n\
-    <default>%i</default>\n\
-    <current>%i</current>\n\
-</boolean>",
-       p.id(),label(),desc(),def(),cur());
+"%9$*6$s<boolean id=\"%1$s\">\n\
+%9$*7$s<about>\n\
+%9$*8$s<label>%2$s</label>\n\
+%9$*8$s<description>%3$s</description>\n\
+%9$*7$s</about>\n\
+%9$*7$s<default>%4$i</default>\n\
+%9$*7$s<current>%5$i</current>\n\
+%9$*6$s</boolean>",
+       p.id(),label(),desc(),def(),cur(),indent,l1width,l2width,sp);
 
     return _tmpBuf.bytes();
Index: /trunk/src/objects/RpBoolean.h
===================================================================
--- /trunk/src/objects/RpBoolean.h	(revision 1559)
+++ /trunk/src/objects/RpBoolean.h	(revision 1560)
@@ -34,5 +34,5 @@
         Accessor<int> cur;
 
-        const char *xml();
+        const char *xml(size_t indent, size_t tabstop);
         const int is() const;
 };
Index: /trunk/src/objects/RpChoice.cc
===================================================================
--- /trunk/src/objects/RpChoice.cc	(revision 1559)
+++ /trunk/src/objects/RpChoice.cc	(revision 1560)
@@ -150,16 +150,21 @@
 
 const char *
-Choice::xml()
-{
+Choice::xml(size_t indent, size_t tabstop)
+{
+    size_t l1width = indent + tabstop;
+    size_t l2width = indent + (2*tabstop);
+    size_t l3width = indent + (3*tabstop);
+    const char *sp = "";
+
     Path p(path());
     _tmpBuf.clear();
 
     _tmpBuf.appendf(
-"<choice id='%s'>\n\
-    <about>\n\
-        <label>%s</label>\n\
-        <description>%s</description>\n\
-    </about>\n",
-       p.id(),label(),desc());
+"%7$*4$s<choice id='%1$s'>\n\
+%7$*5$s<about>\n\
+%7$*6$s<label>%2$s</label>\n\
+%7$*6$s<description>%3$s</description>\n\
+%7$*5$s</about>\n",
+       p.id(),label(),desc(),indent,l1width,l2width,sp);
 
     Rp_ChainLink *l = NULL;
@@ -168,20 +173,20 @@
         option *op = (option *)Rp_ChainGetValue(l);
         _tmpBuf.appendf(
-"    <option>\n\
-        <about>\n\
-            <label>%s</label>\n\
-            <description>%s</description>\n\
-        </about>\n\
-        <value>%s</value>\n\
-    </option>\n",
-           op->label(),op->desc(),op->val());
+"%7$*4$s<option>\n\
+%7$*5$s<about>\n\
+%7$*6$s<label>%1$s</label>\n\
+%7$*6$s<description>%2$s</description>\n\
+%7$*5$s</about>\n\
+%7$*5$s<value>%3$s</value>\n\
+%7$*4$s</option>\n",
+           op->label(),op->desc(),op->val(),l1width,l2width,l3width,sp);
         l = Rp_ChainNextLink(l);
     }
 
     _tmpBuf.appendf(
-"    <default>%s</default>\n\
-    <current>%s</current>\n\
-</choice>",
-       def(),cur());
+"%5$*4$s<default>%1$s</default>\n\
+%5$*4$s<current>%2$s</current>\n\
+%5$*3$s</choice>",
+       def(),cur(),indent,l1width,sp);
 
     return _tmpBuf.bytes();
Index: /trunk/src/objects/RpChoice.h
===================================================================
--- /trunk/src/objects/RpChoice.h	(revision 1559)
+++ /trunk/src/objects/RpChoice.h	(revision 1560)
@@ -41,5 +41,5 @@
         Choice& delOption ( const char *label);
 
-        const char *xml();
+        const char *xml(size_t indent, size_t tabstop);
         const int is() const;
 
Index: /trunk/src/objects/RpCurve.cc
===================================================================
--- /trunk/src/objects/RpCurve.cc	(revision 1559)
+++ /trunk/src/objects/RpCurve.cc	(revision 1560)
@@ -259,6 +259,10 @@
 
 const char *
-Curve::xml()
-{
+Curve::xml(size_t indent, size_t tabstop)
+{
+    size_t l1width = indent + tabstop;
+    size_t l2width = indent + (2*tabstop);
+    const char *sp = "";
+
     Path p(path());
 
@@ -267,14 +271,17 @@
 
     const double *dataArr[dims()];
+    const char *type = propstr("type");
 
     _tmpBuf.clear();
 
     _tmpBuf.appendf(
-"<curve id=\"%s\">\n\
-    <about>\n\
-        <group>%s</group>\n\
-        <label>%s</label>\n\
-        <description>%s</description>\n\
-    </about>\n", p.id(),group(),label(),desc());
+"%9$*6$s<curve id=\"%1$s\">\n\
+%9$*7$s<about>\n\
+%9$*8$s<group>%2$s</group>\n\
+%9$*8$s<label>%3$s</label>\n\
+%9$*8$s<description>%4$s</description>\n\
+%9$*8$s<type>%5$s</type>\n\
+%9$*7$s</about>\n",
+        p.id(),group(),label(),desc(),type,indent,l1width,l2width,sp);
 
     for (size_t dim=0; dim < dims(); dim++) {
@@ -283,15 +290,15 @@
         dataArr[dim] = tmpAxis->data();
         _tmpBuf.appendf(
-"    <%s>\n\
-        <label>%s</label>\n\
-        <description>%s</description>\n\
-        <units>%s</units>\n\
-        <scale>%s</scale>\n\
-    </%s>\n",
+"%8$*6$s<%1$s>\n\
+%8$*7$s<label>%2$s</label>\n\
+%8$*7$s<description>%3$s</description>\n\
+%8$*7$s<units>%4$s</units>\n\
+%8$*7$s<scale>%5$s</scale>\n\
+%8$*6$s</%1$s>\n",
         tmpAxis->name(), tmpAxis->label(), tmpAxis->desc(),
-        tmpAxis->units(), tmpAxis->scale(), tmpAxis->name());
-    }
-
-    _tmpBuf.append("    <component>\n        <xy>\n");
+        tmpAxis->units(), tmpAxis->scale(),l1width,l2width,sp);
+    }
+
+    _tmpBuf.appendf("%3$*1$s<component>\n%3$*2$s<xy>\n",l1width,l2width,sp);
     for (size_t idx=0; idx < nmemb; idx++) {
         for(size_t dim=0; dim < dims(); dim++) {
@@ -300,6 +307,6 @@
         _tmpBuf.append("\n",1);
     }
-    _tmpBuf.append("        </xy>\n    </component>\n</curve>");
-    _tmpBuf.append("\0",1);
+    _tmpBuf.appendf("%4$*3$s</xy>\n%4$*2$s</component>\n%4$*1$s</curve>",
+        indent, l1width, l2width, sp);
 
     return _tmpBuf.bytes();
Index: /trunk/src/objects/RpCurve.h
===================================================================
--- /trunk/src/objects/RpCurve.h	(revision 1559)
+++ /trunk/src/objects/RpCurve.h	(revision 1560)
@@ -48,5 +48,5 @@
         size_t dims() const;
 
-        const char *xml();
+        const char *xml(size_t indent, size_t tabstop);
         const int is() const;
 
Index: /trunk/src/objects/RpHistogram.cc
===================================================================
--- /trunk/src/objects/RpHistogram.cc	(revision 1559)
+++ /trunk/src/objects/RpHistogram.cc	(revision 1560)
@@ -315,6 +315,10 @@
 
 const char *
-Histogram::xml()
-{
+Histogram::xml(size_t indent, size_t tabstop)
+{
+    size_t l1width = indent + tabstop;
+    size_t l2width = indent + (2*tabstop);
+    const char *sp = "";
+
     Path p(path());
 
@@ -327,10 +331,11 @@
 
     _tmpBuf.appendf(
-"<histogram id=\"%s\">\n\
-    <about>\n\
-        <group>%s</group>\n\
-        <label>%s</label>\n\
-        <description>%s</description>\n\
-    </about>\n", p.id(),group(),label(),desc());
+"%8$*5$s<histogram id=\"%1$s\">\n\
+%8$*6$s<about>\n\
+%8$*7$s<group>%2$s</group>\n\
+%8$*7$s<label>%3$s</label>\n\
+%8$*7$s<description>%4$s</description>\n\
+%8$*6$s</about>\n",
+        p.id(),group(),label(),desc(),indent,l1width,l2width,sp);
 
     for (size_t dim=0; dim < dims(); dim++) {
@@ -342,11 +347,11 @@
         }
         _tmpBuf.appendf(
-"    <%s>\n\
-        <label>%s</label>\n\
-        <description>%s</description>\n\
-        <units>%s</units>\n\
-        <scale>%s</scale>\n",
+"%8$*6$s<%1$s>\n\
+%8$*7$s<label>%2$s</label>\n\
+%8$*7$s<description>%3$s</description>\n\
+%8$*7$s<units>%4$s</units>\n\
+%8$*7$s<scale>%5$s</scale>\n",
         tmpAxis->name(), tmpAxis->label(), tmpAxis->desc(),
-        tmpAxis->units(), tmpAxis->scale());
+        tmpAxis->units(), tmpAxis->scale(),l1width,l2width,sp);
 
         if (_markerList != NULL) {
@@ -355,13 +360,13 @@
                 AxisMarker *m = (AxisMarker *) Rp_ChainGetValue(l);
                 if (strcmp(tmpAxis->name(),m->axisName()) == 0) {
-                    _tmpBuf.append(m->xml());
+                    _tmpBuf.append(m->xml(indent+tabstop,tabstop));
                 }
                 l = Rp_ChainNextLink(l);
             }
         }
-        _tmpBuf.appendf("    </%s>\n",tmpAxis->name());
-    }
-
-    _tmpBuf.append("    <component>\n        <xhw>\n");
+        _tmpBuf.appendf("%3$*2$s</%1$s>\n",tmpAxis->name(),l1width,sp);
+    }
+
+    _tmpBuf.appendf("%3$*1$s<component>\n%3$*2$s<xhw>\n",l1width,l2width,sp);
     for (size_t idx=0; idx < nmemb; idx++) {
         for (size_t dim=0; dim < dims(); dim++) {
@@ -370,6 +375,6 @@
         _tmpBuf.append("\n",1);
     }
-    _tmpBuf.append("        </xhw>\n    </component>\n</curve>");
-    _tmpBuf.append("\0",1);
+    _tmpBuf.appendf("%4$*3$s</xhw>\n%4$*2$s</component>\n%4$*1$s</curve>",
+        indent,l1width,l2width,sp);
 
     return _tmpBuf.bytes();
Index: /trunk/src/objects/RpHistogram.h
===================================================================
--- /trunk/src/objects/RpHistogram.h	(revision 1559)
+++ /trunk/src/objects/RpHistogram.h	(revision 1560)
@@ -73,5 +73,5 @@
         size_t nbins(void) const;
 
-        const char *xml();
+        const char *xml(size_t indent, size_t tabstop);
         const int is(void) const;
 
Index: /trunk/src/objects/RpNumber.cc
===================================================================
--- /trunk/src/objects/RpNumber.cc	(revision 1559)
+++ /trunk/src/objects/RpNumber.cc	(revision 1560)
@@ -15,4 +15,7 @@
 #include "RpUnits.h"
 #include "RpSimpleBuffer.h"
+#include "RpUnitsCInterface.h"
+#include "RpParserXML.h"
+#include "RpPath.h"
 
 using namespace Rappture;
@@ -24,4 +27,6 @@
      _presets (NULL)
 {
+    // FIXME: empty names should be autoname'd
+    this->name("");
     this->path("");
     this->label("");
@@ -31,9 +36,9 @@
     this->min(0.0);
     this->max(0.0);
-    // need to set this to the None unit
+    // FIXME: empty units should be set to the None unit
     // this->units(units);
 }
 
-Number::Number(const char *path, const char *units, double val)
+Number::Number(const char *name, const char *units, double val)
    : Object (),
      _minSet (0),
@@ -43,5 +48,6 @@
     const RpUnits *u = NULL;
 
-    this->path(path);
+    this->name(name);
+    this->path("");
     this->label("");
     this->desc("");
@@ -58,5 +64,5 @@
 }
 
-Number::Number(const char *path, const char *units, double val,
+Number::Number(const char *name, const char *units, double val,
                double min, double max, const char *label,
                const char *desc)
@@ -68,5 +74,6 @@
     const RpUnits *u = NULL;
 
-    this->path(path);
+    this->name(name);
+    this->path("");
     this->label(label);
     this->desc(desc);
@@ -112,5 +119,5 @@
     this->units(o.units());
 
-    // need to copy _presets
+    // FIXME: need to copy _presets
 }
 
@@ -225,4 +232,30 @@
 
     return *this;
+}
+
+Number&
+Number::addPreset(const char *label, const char *desc, const char *val)
+{
+    double valval = 0.0;
+    const char *valunits = "";
+    char *endptr = NULL;
+    int result = 0;
+
+    std::string vstr = RpUnits::convert(val,"",RPUNITS_UNITS_OFF,&result);
+    if (result) {
+        // probably shouldnt trust this result
+        fprintf(stderr,"error in RpUnits::convert in addPreset\n");
+    }
+    size_t len = vstr.length();
+    valunits = val+len;
+
+    valval = strtod(val,&endptr);
+    if ( (endptr == val) || (endptr != valunits) ) {
+        // error? strtod was not able to find the same
+        // units location as RpUnits::convert
+        fprintf(stderr,"error while parsing units in addPreset\n");
+    }
+
+    return addPreset(label,desc,valval,valunits);
 }
 
@@ -276,33 +309,120 @@
 
 const char *
-Number::xml()
-{
+Number::xml(size_t indent, size_t tabstop)
+{
+    size_t l1width = indent + (1*tabstop);
+    size_t l2width = indent + (2*tabstop);
+    const char *sp = "";
+
     Path p(path());
     _tmpBuf.clear();
 
     _tmpBuf.appendf(
-"<number id='%s'>\n\
-    <about>\n\
-        <label>%s</label>\n\
-        <description>%s</description>\n\
-    </about>\n\
-    <units>%s</units>\n",
-       p.id(),label(),desc(),units());
+"%8$*5$s<number id='%1$s'>\n\
+%8$*6$s<about>\n\
+%8$*7$s<label>%2$s</label>\n\
+%8$*7$s<description>%3$s</description>\n\
+%8$*6$s</about>\n\
+%8$*6$s<units>%4$s</units>\n",
+       p.id(),label(),desc(),units(),indent,l1width,l2width,sp);
 
     if (_minSet) {
-        _tmpBuf.appendf("    <min>%g%s</min>\n", min(),units());
+        _tmpBuf.appendf("%4$*3$s<min>%1$g%2$s</min>\n", min(),units(),l1width,sp);
     }
     if (_maxSet) {
-        _tmpBuf.appendf("    <max>%g%s</max>\n", max(),units());
+        _tmpBuf.appendf("%4$*3$s<max>%1$g%2$s</max>\n", max(),units(),l1width,sp);
     }
 
     _tmpBuf.appendf(
-"    <default>%g%s</default>\n\
-    <current>%g%s</current>\n\
-</number>",
-       def(),units(),cur(),units());
+"%6$*5$s<default>%1$g%3$s</default>\n\
+%6$*5$s<current>%2$g%3$s</current>\n\
+%6$*4$s</number>",
+       def(),cur(),units(),indent,l1width,sp);
 
     return _tmpBuf.bytes();
 }
+
+/**********************************************************************/
+// METHOD: xml(const char *xmltext)
+/// configure the object based on Rappture1.1 xmltext
+/**
+ * Configure the object based on the provided xml
+ */
+
+void
+Number::xml(const char *xmltext)
+{
+    Rp_ParserXml *p = NULL;
+
+    p = Rp_ParserXmlCreate();
+
+    Rp_ParserXmlParse(p, xmltext);
+
+    Rp_TreeNode node = Rp_ParserXmlElement(p,NULL);
+    name(Rp_ParserXmlNodeId(p,node));
+    label(Rp_ParserXmlGet(p,"about.label"));
+    desc(Rp_ParserXmlGet(p,"about.description"));
+    units(Rp_ParserXmlGet(p,"units"));
+    minFromStr(Rp_ParserXmlGet(p,"min"));
+    maxFromStr(Rp_ParserXmlGet(p,"max"));
+    defFromStr(Rp_ParserXmlGet(p,"default"));
+    curFromStr(Rp_ParserXmlGet(p,"current"));
+
+    // collect info about the preset values
+    Rp_Chain *childChain = Rp_ChainCreate();
+    Rp_ParserXmlChildren(p,NULL,"preset",childChain);
+    Rp_ChainLink *l = Rp_ChainFirstLink(childChain);
+    while (l != NULL) {
+        Rp_TreeNode presetNode = (Rp_TreeNode) Rp_ChainGetValue(l);
+        Rp_ParserXmlBaseNode(p,presetNode);
+
+        const char *presetlabel = Rp_ParserXmlGet(p,"label");
+        const char *presetdesc = Rp_ParserXmlGet(p,"description");
+        const char *presetvalue = Rp_ParserXmlGet(p,"value");
+        addPreset(presetlabel,presetdesc,presetvalue);
+
+
+        l = Rp_ChainNextLink(l);
+    }
+
+    Rp_ChainDestroy(childChain);
+
+    // return the base node to the tree root
+    Rp_ParserXmlBaseNode(p,NULL);
+}
+
+/**********************************************************************/
+// METHOD: tree()
+/// return the object as a tree
+/**
+ * Represent the object as a tree.
+ * An Rp_TreeNode is returned.
+ */
+
+/*
+Rp_TreeNode
+tree()
+{
+    return NULL;
+}
+*/
+
+/**********************************************************************/
+// METHOD: tree(Rp_TreeNode root)
+/// construct a number object from the provided tree
+/**
+ * construct a number object from the provided tree
+ */
+
+/*
+void
+tree(
+    Rp_TreeNode root)
+{
+    if (root == NULL) {
+        // FIXME: setup error
+    }
+}
+*/
 
 /**********************************************************************/
@@ -321,4 +441,98 @@
 
 
+/**********************************************************************/
+// METHOD: minFromStr()
+/// xml helper function to receive min value as a string
+/**
+ * convert string to value and units and store as min
+ */
+
+void
+Number::minFromStr(
+    const char *val)
+{
+    double numericVal = 0;
+    int err = 0;
+
+    numericVal = rpConvertDbl(val,units(),&err);
+
+    if (!err) {
+        min(numericVal);
+    } else {
+        // FIXME: add error code
+    }
+}
+
+/**********************************************************************/
+// METHOD: maxFromStr()
+/// xml helper function to receive max value as a string
+/**
+ * convert string to value and units and store as max
+ */
+
+void
+Number::maxFromStr(
+    const char *val)
+{
+    double numericVal = 0;
+    int err = 0;
+
+    numericVal = rpConvertDbl(val,units(),&err);
+
+    if (!err) {
+        max(numericVal);
+    } else {
+        // FIXME: add error code
+    }
+}
+
+/**********************************************************************/
+// METHOD: defFromStr()
+/// xml helper function to receive default value as a string
+/**
+ * convert string to value and units and store as default
+ */
+
+void
+Number::defFromStr(
+    const char *val)
+{
+    double numericVal = 0;
+    int err = 0;
+
+    numericVal = rpConvertDbl(val,units(),&err);
+
+    if (!err) {
+        def(numericVal);
+    } else {
+        // FIXME: add error code
+    }
+}
+
+/**********************************************************************/
+// METHOD: currFromStr()
+/// xml helper function to receive current value as a string
+/**
+ * convert string to value and units and store as current
+ */
+
+void
+Number::curFromStr(
+    const char *val)
+{
+    double numericVal = 0;
+    int err = 0;
+
+    numericVal = rpConvertDbl(val,units(),&err);
+
+    if (!err) {
+        cur(numericVal);
+    } else {
+        // FIXME: add error code
+    }
+}
+
+
+
 // -------------------------------------------------------------------- //
 
Index: /trunk/src/objects/RpNumber.h
===================================================================
--- /trunk/src/objects/RpNumber.h	(revision 1559)
+++ /trunk/src/objects/RpNumber.h	(revision 1560)
@@ -22,7 +22,7 @@
 
         Number();
-        Number(const char *path, const char *units, double val);
+        Number(const char *name, const char *units, double val);
 
-        Number(const char *path, const char *units, double val,
+        Number(const char *name, const char *units, double val,
                double min, double max, const char *label,
                const char *desc);
@@ -52,8 +52,23 @@
                           double val, const char *units);
 
+        Number& addPreset(const char *label, const char *desc,
+                          const char *val);
+
         Number& delPreset(const char *label);
 
-        const char* xml();
+        const char* xml(size_t indent, size_t tabstop);
+        void xml(const char *xmltext);
+
+        /*
+        Rp_TreeNode tree();
+        void tree(Rp_TreeNode root);
+        */
+
         const int is() const;
+
+        void minFromStr(const char *val);
+        void maxFromStr(const char *val);
+        void defFromStr(const char *val);
+        void curFromStr(const char *val);
 
     private:
Index: /trunk/src/objects/RpObject.cc
===================================================================
--- /trunk/src/objects/RpObject.cc	(revision 1559)
+++ /trunk/src/objects/RpObject.cc	(revision 1560)
@@ -25,4 +25,5 @@
 
 Object::Object (
+    const char *name,
     const char *path,
     const char *label,
@@ -31,4 +32,5 @@
     const char *color   )
 {
+    this->name(name);
     this->path(path);
     this->label(label);
@@ -40,4 +42,5 @@
 Object::Object(const Object& o)
 {
+    name(o.name());
     path(o.path());
     label(o.label());
@@ -58,4 +61,16 @@
 
 const char*
+Object::name() const
+{
+    return propstr("name");
+}
+
+void
+Object::name(const char *p)
+{
+    propstr("name",p);
+}
+
+const char*
 Object::path() const
 {
@@ -201,8 +216,15 @@
     }
 
+    if (val == NULL) {
+        // no value provided, no value stored.
+        // FIXME: raise error.
+        return;
+    }
+
     // set the value
     // FIXME: this is suspect,
     // want to use void's and void*'s but c++ wont let me
     // g++ says there is no delete[] for void*
+    // FIXME: can probably just get the length and use property() fxn
     size_t l = strlen(val);
     str = new char[l+1];
@@ -276,5 +298,5 @@
 
 const char *
-Object::xml() const
+Object::xml(size_t indent, size_t tabstop) const
 {
     return NULL;
Index: /trunk/src/objects/RpObject.h
===================================================================
--- /trunk/src/objects/RpObject.h	(revision 1559)
+++ /trunk/src/objects/RpObject.h	(revision 1560)
@@ -24,5 +24,6 @@
     public:
         Object ();
-        Object (const char *path,
+        Object (const char *name,
+                const char *path,
                 const char *label,
                 const char *desc,
@@ -31,4 +32,7 @@
         Object (const Object& o);
         virtual ~Object();
+
+        const char *name(void) const;
+        void name(const char *p);
 
         const char *path(void) const;
@@ -45,5 +49,5 @@
 
         const char *color(void) const;
-        void color(const char *);
+        void color(const char *p);
 
         // void *icon(void) const;
@@ -66,5 +70,5 @@
 
         // get the Rappture1.1 xml text for this object
-        virtual const char *xml() const;
+        virtual const char *xml(size_t indent, size_t tabstop) const;
 
         // set the object properties based on Rappture1.1 xml text
Index: /trunk/src/objects/RpParserXML.cc
===================================================================
--- /trunk/src/objects/RpParserXML.cc	(revision 1560)
+++ /trunk/src/objects/RpParserXML.cc	(revision 1560)
@@ -0,0 +1,694 @@
+/*
+ * ----------------------------------------------------------------------
+ *  Rappture 2.0 XML Parser Object Source
+ *
+ * ======================================================================
+ *  AUTHOR:  Derrick Kearney, Purdue University
+ *  Copyright (c) 2005-2009  Purdue Research Foundation
+ *
+ *  See the file "license.terms" for information on usage and
+ *  redistribution of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ * ======================================================================
+ */
+
+#include "RpParserXML.h"
+#include "RpSimpleBuffer.h"
+#include "RpPath.h"
+
+static const char *Rp_ParserXml_Field_ID = "id";
+static const char *Rp_ParserXml_Field_VALUE = "value";
+static const char *Rp_ParserXml_Field_VISITED = "visited";
+
+struct Rp_ParserXmlStruct {
+    Rp_Tree tree;
+    Rp_TreeNode curr;
+    Rappture::Path *path;
+    Rappture::SimpleCharBuffer *buf;
+};
+
+
+static void XMLCALL
+Rp_ParserXmlStartHandler(
+    void *data,
+    const char *el,
+    const char **attr)
+{
+    Rp_ParserXml *inf = (Rp_ParserXml *) data;
+    size_t i = 0;
+
+    inf->curr = Rp_TreeCreateNode(inf->tree, inf->curr, el, -1);
+
+    // store the attributes in the node
+    while (attr[i] != NULL) {
+        const char *attrName = attr[i++];
+        size_t attrValueLen = strlen(attr[i]);
+        // FIXME: memory leak originating from this new call
+        // I'm not sure where/when the attrValue is deleted yet
+        char *attrValue = new char[attrValueLen+1];
+        strcpy(attrValue,attr[i++]);
+        Rp_TreeSetValue(inf->tree,inf->curr,attrName,(void *)attrValue);
+    }
+    inf->path->add(el);
+}
+
+static void XMLCALL
+Rp_ParserXmlEndHandler(
+    void *data,
+    const char *el)
+{
+    Rp_ParserXml *inf = (Rp_ParserXml *) data;
+
+    if (inf == NULL) {
+        return;
+    }
+
+    char *value = NULL;
+    Rp_TreeGetValue(inf->tree,inf->curr,Rp_ParserXml_Field_VALUE,(void **)&value);
+
+    // strip trailing spaces
+    int i = 0;
+    for (i = strlen(value)-1; i >= 0; i--) {
+        if (isspace(value[i])) {
+            value[i] = '\0';
+        } else {
+            break;
+        }
+    }
+
+    // strip leading spaces
+    int j = 0;
+    for (j = 0; j < i; j++) {
+        if (isspace(value[j])) {
+            value[j] = '\0';
+        } else {
+            break;
+        }
+    }
+
+    if (j > 0) {
+        // reallocate the trimmed string
+        char *newValue = new char[i-j+1+1];
+        strcpy(newValue,value+j);
+        Rp_TreeSetValue(inf->tree,inf->curr,Rp_ParserXml_Field_VALUE,(void *)newValue);
+        delete value;
+        value = NULL;
+    }
+
+    inf->path->del();
+    inf->curr = Rp_TreeNodeParent(inf->curr);
+}
+
+void
+Rp_ParserXmlDefaultCharHandler(
+    void* data,
+    XML_Char const* s,
+    int len)
+{
+    Rp_ParserXml *inf = (Rp_ParserXml *) data;
+
+    if (inf == NULL) {
+        return;
+    }
+
+    // FIXME: where/when is this deallocated
+    char *d = new char[len+1];
+
+    if ( s != NULL) {
+        strncpy(d,s,len);
+    }
+
+    d[len] = '\0';
+    Rp_TreeSetValue(inf->tree,inf->curr,Rp_ParserXml_Field_VALUE,(void *)d);
+}
+
+Rp_ParserXml *
+Rp_ParserXmlCreate()
+{
+    Rp_ParserXml *p = new Rp_ParserXml();
+
+    Rp_TreeCreate("rapptureTree",&(p->tree));
+    p->curr = Rp_TreeRootNode(p->tree);
+    p->path = new Rappture::Path();
+    p->buf = new Rappture::SimpleCharBuffer();
+
+
+    return p;
+}
+
+void
+Rp_ParserXmlDestroy(Rp_ParserXml **p)
+{
+    if (p == NULL) {
+        return;
+    }
+
+    if (*p == NULL) {
+        return;
+    }
+
+    Rp_TreeReleaseToken((*p)->tree);
+    delete (*p)->buf;
+    delete (*p)->path;
+    delete *p;
+    p = NULL;
+}
+
+void
+Rp_ParserXmlParse(
+    Rp_ParserXml *p,
+    const char *xml)
+{
+    if (xml == NULL) {
+        return;
+    }
+
+    XML_Parser parser = XML_ParserCreate(NULL);
+    XML_SetUserData(parser,p);
+    XML_SetElementHandler(parser, Rp_ParserXmlStartHandler,
+        Rp_ParserXmlEndHandler);
+    XML_SetDefaultHandlerExpand(parser, Rp_ParserXmlDefaultCharHandler);
+
+    int done = 1;
+    int len = 0;
+
+    len = strlen(xml);
+    if (XML_Parse(parser, xml, len, done) == XML_STATUS_ERROR) {
+        fprintf(stderr, "Parse error at line %lu:\n%s\n",
+                XML_GetCurrentLineNumber(parser),
+                XML_ErrorString(XML_GetErrorCode(parser)));
+        exit(-1);
+    }
+
+    XML_ParserFree(parser);
+
+    // reset the root node
+    p->curr = Rp_TreeFirstChild(Rp_TreeRootNode(p->tree));
+
+    return;
+}
+
+Rp_TreeNode
+Rp_ParserXmlCreateNode(
+    Rp_ParserXml *p,
+    Rp_TreeNode parent,
+    const char *type,
+    const char *id)
+{
+    if (!p->tree || !parent || !type) {
+        fprintf(stderr,"failed to create node because of invalid data\n");
+        return NULL;
+    }
+
+    Rp_TreeNode child = Rp_TreeCreateNode(p->tree, parent, type, -1);
+
+    if (id != NULL) {
+        size_t attrValueLen = strlen(id);
+        // FIXME: memory leak originating from this new call
+        // I'm not sure where/when the attrValue is deleted yet
+        char *attrValue = new char[attrValueLen+1];
+        strcpy(attrValue,id);
+        Rp_TreeSetValue(p->tree,child,Rp_ParserXml_Field_ID,(void *)attrValue);
+    }
+
+    return child;
+}
+
+Rp_TreeNode
+Rp_ParserXmlSearch(
+    Rp_ParserXml *p,
+    const char *path,
+    int create)
+{
+    Rappture::Path pathObj(path);
+    Rp_TreeNode parent = NULL;
+    Rp_TreeNode child = NULL;
+    size_t degree = 0;
+
+    if (p == NULL) {
+        return NULL;
+    }
+
+    // start searching from the base node
+    parent = p->curr;
+
+    // if (path == NULL) return the base node
+    child = p->curr;
+
+    pathObj.first();
+    while ( (!pathObj.eof()) &&
+            (parent != NULL) ) {
+
+        const char *childName = pathObj.type();
+        const char *searchChildId = pathObj.id();
+
+        child = Rp_TreeFindChild(parent,childName);
+        if (child == NULL) {
+            // no nodes with the name childName exist
+            // FIXME: use the RPXML_CREATE flag
+            if (create) {
+                for (size_t i = 1; i <= pathObj.degree(); i++) {
+                    child = Rp_ParserXmlCreateNode(p, parent,
+                                childName, searchChildId);
+                    if (child == NULL) {
+                        break;
+                    }
+                }
+            } else {
+                fprintf(stderr,"invalid path %s at %s\n",path,childName);
+                break;
+            }
+        }
+
+        //FIXME: rewrite the child id search logic
+        const char *id = NULL;
+        Rp_TreeGetValue(p->tree,child, Rp_ParserXml_Field_ID,(void **)&id);
+        while (searchChildId && id) {
+
+            // check for matching child id and degree
+            if ((*searchChildId == *id) &&
+                (strcmp(searchChildId,id) == 0)) {
+                // found child with matching id
+                // check degree
+                degree++;
+                if (degree == pathObj.degree()) {
+                    // degrees match, return result
+                    break;
+                }
+            }
+
+            // check the next child to see if it has the correct id
+            child = Rp_TreeNextSibling(child);
+            if (child == NULL) {
+                // end of the sibling list
+                // create new node? or return NULL pointer
+                // FIXME: use the RPXML_CREATE flag
+                if (create) {
+                    child = Rp_ParserXmlCreateNode(p, parent,
+                                childName, searchChildId);
+                    if (child == NULL) {
+                        break;
+                    }
+                } else {
+                    // exit, child not found
+                    break;
+                }
+            }
+            id = NULL;
+            Rp_TreeGetValue(p->tree,child,Rp_ParserXml_Field_ID,(void **)&id);
+        }
+
+        parent = child;
+        pathObj.next();
+    }
+
+    return child;
+}
+
+const char *
+Rp_ParserXmlGet(
+    Rp_ParserXml *p,
+    const char *path)
+{
+    const char *value = NULL;
+    Rp_TreeNode child = NULL;
+
+    child = Rp_ParserXmlSearch(p, path, 0);
+    if (child != NULL) {
+        Rp_TreeGetValue(p->tree,child,Rp_ParserXml_Field_VALUE,(void **)&value);
+    }
+
+    return value;
+}
+
+void
+Rp_ParserXmlPut(
+    Rp_ParserXml *p,
+    const char *path,
+    const char *val,
+    int append)
+{
+    const char *oldval = NULL;
+    char *newval = NULL;
+    size_t oldval_len = 0;
+    size_t val_len = 0;
+
+    if (val == NULL) {
+        // no value, do nothing
+        return;
+    }
+
+    Rp_TreeNode child = Rp_ParserXmlSearch(p, path, 1);
+
+    if (child != NULL) {
+        // check to see if there is already a value
+        if (RP_OK == Rp_TreeGetValue(p->tree,child,
+                        Rp_ParserXml_Field_VALUE,
+                        (void **)&oldval)) {
+            if (oldval != NULL) {
+                // FIXME: use the RPXML_APPEND flag
+                if (append) {
+                    oldval_len = strlen(oldval);
+                    val_len = strlen(val);
+                    newval = new char[oldval_len + val_len + 1];
+                    strncpy(newval,oldval,oldval_len);
+                }
+                // free the old data
+                delete(oldval);
+                oldval = NULL;
+            }
+        }
+
+        // allocate space for our new value if needed
+        if (newval == NULL) {
+            // set the new value for the node
+            val_len = strlen(val);
+            newval = new char[val_len + 1];
+        }
+
+        strcpy(newval+oldval_len,val);
+
+        // set the value of the child node
+        if (RP_ERROR == Rp_TreeSetValue(p->tree,child,
+                            Rp_ParserXml_Field_VALUE,
+                            (void *)newval)) {
+            fprintf(stderr,"error while setting value of %s\n",path);
+        }
+    }
+    return;
+}
+
+Rp_Tree
+Rp_ParserXmlTreeClient(
+    Rp_ParserXml *p)
+{
+    if (p == NULL) {
+        return NULL;
+    }
+    Rp_Tree newTree = NULL;
+    // create a new token for the tree and return it to the caller
+    Rp_TreeGetTokenFromToken(p->tree,&newTree);
+    return newTree;
+}
+
+int
+printXmlData(
+    Rp_TreeNode node,
+    ClientData clientData,
+    int order)
+{
+    Rp_ParserXml *p = (Rp_ParserXml *) clientData;
+
+    Rappture::Path labelComp(Rp_TreeNodeLabel(node));
+    const char *label = labelComp.type();
+    const char *value = NULL;
+
+    size_t width = (Rp_TreeNodeDepth(p->tree,node)-1)*PARSERXML_LEVEL_WIDTH;
+    const char *sp = "";
+    int *visited = NULL;
+
+    Rp_TreeGetValue(p->tree,node,Rp_ParserXml_Field_VALUE,(void **)&value);
+    size_t valLen = strlen(value);
+
+    if (!Rp_TreeValueExists(p->tree,node,Rp_ParserXml_Field_VISITED)) {
+        visited = new int();
+        *visited = 0;
+
+        p->buf->appendf("%3$*2$s<%1$s",label,width,sp);
+
+        // go through all attributes and place them in the tag
+        Rp_TreeKey attrName = NULL;
+        Rp_TreeKeySearch search;
+        attrName = Rp_TreeFirstKey (p->tree, node, &search);
+        while (attrName) {
+            if ((*Rp_ParserXml_Field_VALUE != *attrName) &&
+                (strcmp(Rp_ParserXml_Field_VALUE,attrName) != 0)) {
+                const char *attrValue = NULL;
+                Rp_TreeGetValueByKey(p->tree,node,attrName,(void**)&attrValue);
+                p->buf->appendf(" %s=\"%s\"",attrName,attrValue);
+            }
+            attrName = Rp_TreeNextKey(p->tree, &search);
+        }
+
+        // close the opening tag
+        p->buf->appendf(">");
+
+        // append the value of the tag if any
+        if ( (value != NULL ) &&
+             (valLen != 0) ) {
+            p->buf->appendf("%s",value);
+        } else {
+            p->buf->appendf("\n");
+        }
+
+        // set the "visited" temporary flag so the next time
+        // we encounter this node, we know it is as a closing node
+        Rp_TreeSetValue(p->tree,node,Rp_ParserXml_Field_VISITED,(void *)visited);
+
+    } else {
+        Rp_TreeGetValue(p->tree,node,Rp_ParserXml_Field_VISITED,(void **)&visited);
+        delete visited;
+        Rp_TreeUnsetValue(p->tree,node,Rp_ParserXml_Field_VISITED);
+        if ( (value != NULL ) &&
+             (valLen != 0) ) {
+            p->buf->appendf("</%s>\n",label);
+        } else {
+            p->buf->appendf("%3$*2$s</%1$s>\n",label,width,sp);
+        }
+
+    }
+
+    return RP_OK;
+}
+
+const char *
+Rp_ParserXmlXml(
+    Rp_ParserXml *p)
+{
+    p->buf->clear();
+    p->buf->appendf("<?xml version=\"1.0\"?>\n");
+
+    Rp_TreeNode root = p->curr;
+
+    Rp_TreeApplyDFS(root, printXmlData, (ClientData)p, TREE_PREORDER|TREE_POSTORDER);
+
+    return p->buf->bytes();
+}
+
+int
+printPathVal(
+    Rp_TreeNode node,
+    ClientData clientData,
+    int order)
+{
+    Rp_ParserXml *p = (Rp_ParserXml *) clientData;
+
+    int *visited = NULL;
+
+    if (!Rp_TreeValueExists(p->tree,node,Rp_ParserXml_Field_VISITED)) {
+        // update path
+        p->path->add(Rp_TreeNodeLabel(node));
+
+        const char *id = NULL;
+        if (RP_OK == Rp_TreeGetValue(p->tree,node,Rp_ParserXml_Field_ID,(void **)&id)) {
+            p->path->last();
+            p->path->id(id);
+        }
+
+        const char *value = NULL;
+        if (RP_ERROR == Rp_TreeGetValue(p->tree,node,Rp_ParserXml_Field_VALUE,(void **)&value)) {
+            // error while getting value, exit fxn gracefully?
+            // FIXME: add error code here
+        }
+
+        // append the path and value of the node to our result text
+        if (value && (strlen(value) != 0)) {
+            p->buf->appendf("%s %s\n",p->path->path(),value);
+        }
+
+        // set the "visited" temporary flag so the next time
+        // we encounter this node, we know it is as a closing node
+        visited = new int();
+        *visited = 0;
+        if (RP_ERROR == Rp_TreeSetValue(p->tree,node,Rp_ParserXml_Field_VISITED,(void *)visited)) {
+            // FIXME: error while setting value
+        }
+    } else {
+        // update path
+        p->path->del();
+
+        // delete the "visited" temporary flag from the node
+        if (RP_ERROR == Rp_TreeGetValue(p->tree,node,Rp_ParserXml_Field_VISITED,(void **)&visited)) {
+            // FIXME: error while getting value
+        }
+        delete visited;
+        if (RP_ERROR == Rp_TreeUnsetValue(p->tree,node,Rp_ParserXml_Field_VISITED)) {
+            // FIXME: error while unsetting value
+        }
+    }
+
+    return RP_OK;
+}
+
+const char *
+Rp_ParserXmlPathVal(
+    Rp_ParserXml *p)
+{
+    p->buf->clear();
+
+    // temporarily store p->path so we can use p as ClientData
+    Rappture::Path *tmpPath = p->path;
+    p->path = new Rappture::Path();
+
+    Rp_TreeNode root = p->curr;
+
+    Rp_TreeApplyDFS(root, printPathVal, (ClientData)p, TREE_PREORDER|TREE_POSTORDER);
+
+    // restore the original path
+    delete p->path;
+    p->path = tmpPath;
+
+    return p->buf->bytes();
+}
+
+Rp_TreeNode
+Rp_ParserXmlElement(
+    Rp_ParserXml *p,
+    const char *path)
+{
+    if (p == NULL) {
+        return NULL;
+    }
+
+    return Rp_ParserXmlSearch(p,path,!RPXML_CREATE);
+}
+
+Rp_TreeNode
+Rp_ParserXmlParent(
+    Rp_ParserXml *p,
+    const char *path)
+{
+    if (p == NULL) {
+        return NULL;
+    }
+
+    Rp_TreeNode node = Rp_ParserXmlSearch(p,path,!RPXML_CREATE);
+    if (node == NULL) {
+        return NULL;
+    }
+
+    return Rp_TreeNodeParent(node);
+}
+
+size_t
+Rp_ParserXmlChildren(
+    Rp_ParserXml *p,
+    const char *path,
+    const char *type,
+    Rp_Chain *children)
+{
+    size_t count = 0;
+
+    if (p == NULL) {
+        return count;
+    }
+
+    if (children == NULL) {
+        return count;
+    }
+
+    Rp_TreeNode node = Rp_ParserXmlSearch(p,path,!RPXML_CREATE);
+
+    if (node != NULL) {
+        node = Rp_TreeFindChild(node,type);
+        while (node != NULL) {
+            count++;
+            Rp_ChainAppend(children,(void*)node);
+            node = Rp_TreeFindChildNext(node,type);
+        }
+    }
+    return count;
+}
+
+size_t
+Rp_ParserXmlNumberChildren(
+    Rp_ParserXml *p,
+    const char *path,
+    const char *type)
+{
+    size_t count = 0;
+
+    if (p == NULL) {
+        return count;
+    }
+
+    Rp_TreeNode node = Rp_ParserXmlSearch(p,path,!RPXML_CREATE);
+    if (node != NULL) {
+        node = Rp_TreeFindChild(node,type);
+        while (node != NULL) {
+            count++;
+            node = Rp_TreeFindChildNext(node,type);
+        }
+    }
+
+    return count;
+}
+
+void
+Rp_ParserXmlBaseNode(
+    Rp_ParserXml *p,
+    Rp_TreeNode node)
+{
+    if (p != NULL) {
+        if (node == NULL) {
+            p->curr = Rp_TreeFirstChild(Rp_TreeRootNode(p->tree));
+        } else {
+            p->curr = node;
+        }
+    }
+}
+
+/*
+const char *
+Rp_ParserXmlNodePath(
+    Rp_ParserXml *p,
+    Rp_TreeNode node)
+{
+    Path pathObj("junk");
+
+    const char *type = NULL;
+    const char *id = NULL;
+
+    // FIXME: path's add and del don't work on the current node
+    if (p != NULL) {
+        while (node != p->curr) {
+            type = Rp_TreeNodeLabel(node)
+            Rp_TreeGetValue(p->tree,child, Rp_ParserXml_Field_ID,(void **)&id);
+            pathObj.first();
+            pathObj.add(type);
+            pathObj.id(id);
+            node = Rp_TreeNodeParent(node);
+        }
+    }
+
+    pathObj.first();
+    pathObj.del();
+    return path
+}
+*/
+
+const char *
+Rp_ParserXmlNodeId(
+    Rp_ParserXml *p,
+    Rp_TreeNode node)
+{
+    const char *id = NULL;
+    if (p != NULL) {
+        if (node != NULL) {
+            Rp_TreeGetValue(p->tree,node, Rp_ParserXml_Field_ID,(void **)&id);
+        }
+    }
+    return id;
+}
+
+// -------------------------------------------------------------------- //
+
Index: /trunk/src/objects/RpParserXML.h
===================================================================
--- /trunk/src/objects/RpParserXML.h	(revision 1560)
+++ /trunk/src/objects/RpParserXML.h	(revision 1560)
@@ -0,0 +1,54 @@
+/*
+ * ======================================================================
+ *  AUTHOR:  Derrick Kearney, Purdue University
+ *  Copyright (c) 2005-2009  Purdue Research Foundation
+ *
+ *  See the file "license.terms" for information on usage and
+ *  redistribution of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ * ======================================================================
+ */
+#include <errno.h>
+#include <expat.h>
+#include <string.h>
+#include "RpTree.h"
+#include "RpChain.h"
+
+#ifndef RAPPTURE_PARSER_XML_H
+#define RAPPTURE_PARSER_XML_H
+
+#define PARSERXML_LEVEL_WIDTH 4
+
+enum RapptureParserXmlFlags {
+    RPXML_CREATE=(1<<0),    /* Create the xml path if needed. */
+    RPXML_APPEND=(1<<1),    /* Append data to the data already available. */
+};
+
+
+typedef struct Rp_ParserXmlStruct Rp_ParserXml;
+
+Rp_ParserXml *Rp_ParserXmlCreate();
+void Rp_ParserXmlDestroy(Rp_ParserXml **p);
+
+void Rp_ParserXmlParse(Rp_ParserXml *p, const char *xml);
+Rp_TreeNode Rp_ParserXmlSearch( Rp_ParserXml *p, const char *path, int create);
+const char *Rp_ParserXmlGet(Rp_ParserXml *p, const char *path);
+void Rp_ParserXmlPut(Rp_ParserXml *p, const char *path, const char *val,
+    int append);
+
+Rp_Tree Rp_ParserXmlTreeClient(Rp_ParserXml *p);
+
+Rp_TreeNode Rp_ParserXmlElement(Rp_ParserXml *p, const char *path);
+Rp_TreeNode Rp_ParserXmlParent(Rp_ParserXml *p, const char *path);
+size_t Rp_ParserXmlChildren(Rp_ParserXml *p, const char *path,
+    const char *type, Rp_Chain *children);
+size_t Rp_ParserXmlNumberChildren(Rp_ParserXml *p, const char *path,
+    const char *type);
+void Rp_ParserXmlBaseNode(Rp_ParserXml *p, Rp_TreeNode node);
+
+// const char *Rp_ParserXmlNodePath(Rp_ParserXml *p, Rp_TreeNode node);
+const char *Rp_ParserXmlNodeId(Rp_ParserXml *p, Rp_TreeNode node);
+
+const char *Rp_ParserXmlXml(Rp_ParserXml *p);
+const char *Rp_ParserXmlPathVal(Rp_ParserXml *p);
+
+#endif // RAPPTURE_PARSER_XML_H
Index: /trunk/src/objects/RpPath.cc
===================================================================
--- /trunk/src/objects/RpPath.cc	(revision 1559)
+++ /trunk/src/objects/RpPath.cc	(revision 1560)
@@ -23,4 +23,5 @@
 #include "RpChainHelper.h"
 #include <cstring>
+#include <cstdlib>
 
 using namespace Rappture;
@@ -60,4 +61,5 @@
     _ifs = b._ifs;
 
+    //FIXME: i think this is broken
     Rp_ChainCopy (_pathList, b._pathList, Rp_ChainCharCpyFxn);
 }
@@ -105,4 +107,5 @@
     _ifs = '.';
     _pathList = Rp_ChainCreate();
+    _currLink = Rp_ChainFirstLink(_pathList);
     return;
 }
@@ -134,5 +137,6 @@
     int end,
     int idOpenParen,
-    int idCloseParen)
+    int idCloseParen,
+    size_t degree)
 {
     componentStruct *c = new componentStruct();
@@ -143,4 +147,5 @@
     c->type = NULL;
     c->id = NULL;
+    c->degree = degree;
 
     if (idOpenParen < idCloseParen) {
@@ -171,5 +176,5 @@
         the type and id of the third component are both blank.
         for the above example paths, the id field of the first
-        components, the index component, is NULL.
+        components, the input component, is NULL.
         i don't think there is a way to get a NULL type right now.
     */
@@ -215,4 +220,6 @@
     int idCloseParen = -1;
     componentStruct *c = NULL;
+    size_t degree = 1;
+    char *newEnd = NULL;
 
     Rp_Chain *compList = Rp_ChainCreate();
@@ -227,6 +234,20 @@
         } else if (p[end] == ')') {
             idCloseParen = end;
+        } else if ( (idOpenParen <= idCloseParen) &&
+                    (end != 0) &&
+                    (p[end] >= '0') &&
+                    (p[end] <= '9') ) {
+            degree = (size_t) strtod(p+end, &newEnd);
+            if (degree == 0) {
+                // interpret degree of 0 same as degree of 1
+                degree = 1;
+            }
+            // check if we consumed the _ifs
+            if (*(newEnd-1) == _ifs) {
+                newEnd -= 2;
+            }
+            end += newEnd - (p + end);
         } else if (p[end] == _ifs) {
-            c = __createComponent(p,start,end,idOpenParen,idCloseParen);
+            c = __createComponent(p,start,end,idOpenParen,idCloseParen,degree);
             if (c != NULL) {
                 Rp_ChainAppend(compList,c);
@@ -240,5 +261,5 @@
     }
 
-    c = __createComponent(p,start,end,idOpenParen,idCloseParen);
+    c = __createComponent(p,start,end,idOpenParen,idCloseParen,degree);
     if (c != NULL) {
         Rp_ChainAppend(compList,c);
@@ -335,10 +356,54 @@
 }
 
+bool
+Path::eof ()
+{
+    return (_currLink == NULL);
+}
+
+Path&
+Path::first ()
+{
+    _currLink = Rp_ChainFirstLink(_pathList);
+    return *this;
+}
+
+Path&
+Path::prev ()
+{
+    if (_currLink) {
+        _currLink = Rp_ChainPrevLink(_currLink);
+    }
+    return *this;
+}
+
+Path&
+Path::next ()
+{
+    if (_currLink) {
+        _currLink = Rp_ChainNextLink(_currLink);
+    }
+    return *this;
+}
+
+Path&
+Path::last ()
+{
+    _currLink = Rp_ChainLastLink(_pathList);
+    return *this;
+}
+
+size_t
+Path::count ()
+{
+    return Rp_ChainGetLength(_pathList);
+}
+
 const char *
 Path::component(void)
 {
     Rp_ChainLink *l = NULL;
-    size_t len = 0;
-
+
+    /*
     tmpBuf.clear();
 
@@ -348,5 +413,5 @@
     }
 
-    l = Rp_ChainLastLink(_pathList);
+    l = _currLink;
 
     if (l == NULL) {
@@ -363,19 +428,53 @@
 
     if (c->type != NULL) {
-        len = strlen(c->type);
-        if (len > 0) {
-            tmpBuf.append(c->type,len);
-        }
+        tmpBuf.appendf("%s",c->type);
+    }
+
+    if (c->degree != 1) {
+        tmpBuf.appendf("%zu",c->degree);
     }
 
     if (c->id != NULL) {
-        tmpBuf.append("(",1);
-        len = strlen(c->id);
-        if (len > 0) {
-            tmpBuf.append(c->id,len);
-        }
-        tmpBuf.append(")",1);
-    }
-
+        tmpBuf.appendf("(%s)",c->id);
+    }
+
+    // incase none of the above if statements are hit.
+    tmpBuf.append("\0",1);
+
+    return tmpBuf.bytes();
+    */
+
+
+    if (_pathList == NULL) {
+        return NULL;
+    }
+
+    l = _currLink;
+
+    if (l == NULL) {
+        return NULL;
+    }
+
+    componentStruct *c = (componentStruct *) Rp_ChainGetValue(l);
+
+    if (c == NULL) {
+        return NULL;
+    }
+
+    tmpBuf.clear();
+
+    if (c->type != NULL) {
+        tmpBuf.appendf("%s",c->type);
+    }
+
+    if (c->degree != 1) {
+        tmpBuf.appendf("%zu",c->degree);
+    }
+
+    if (c->id != NULL) {
+        tmpBuf.appendf("(%s)",c->id);
+    }
+
+    // incase none of the above if statements are hit.
     tmpBuf.append("\0",1);
 
@@ -426,15 +525,17 @@
     Rp_ChainDestroy(addList);
 
-    // remove the last component from the current path
-    l = Rp_ChainLastLink(_pathList);
+    // swap the current component from the current path
+    // with the component from the provided path.
+    l = _currLink;
 
     if (l != NULL) {
         componentStruct *last = (componentStruct *) Rp_ChainGetValue(l);
         delete last;
-        Rp_ChainDeleteLink(_pathList,l);
-    }
-
-    // append the new component onto the current path
-    Rp_ChainAppend(_pathList,aLcomp);
+        Rp_ChainSetValue(l,aLcomp);
+    } else {
+        // add a new component as a link
+        // point _currLink to the new component
+        _currLink = Rp_ChainAppend(_pathList,aLcomp);
+    }
 
     __updateBuffer();
@@ -448,4 +549,5 @@
     Rp_ChainLink *l = NULL;
 
+    /*
     tmpBuf.clear();
 
@@ -455,5 +557,5 @@
     }
 
-    l = Rp_ChainLastLink(_pathList);
+    l = _currLink;
 
     if (l == NULL) {
@@ -476,4 +578,23 @@
 
     return tmpBuf.bytes();
+    */
+
+    if (_pathList == NULL) {
+        return NULL;
+    }
+
+    l = _currLink;
+
+    if (l == NULL) {
+        return NULL;
+    }
+
+    componentStruct *c = (componentStruct *) Rp_ChainGetValue(l);
+
+    if (c == NULL) {
+        return NULL;
+    }
+
+    return c->id;
 }
 
@@ -490,6 +611,6 @@
     componentStruct *last = NULL;
 
-    // update the last component from the current path
-    l = Rp_ChainLastLink(_pathList);
+    // update the current component from the current path
+    l = _currLink;
 
     if (l != NULL) {
@@ -499,5 +620,5 @@
         // append the new component onto the current path
         last = new componentStruct;
-        Rp_ChainAppend(_pathList,last);
+        _currLink = Rp_ChainAppend(_pathList,last);
         tmp = new char[1];
         *tmp = '\0';
@@ -520,4 +641,5 @@
     Rp_ChainLink *l = NULL;
 
+    /*
     tmpBuf.clear();
 
@@ -527,5 +649,5 @@
     }
 
-    l = Rp_ChainLastLink(_pathList);
+    l = _currLink;
 
     if (l == NULL) {
@@ -548,4 +670,23 @@
 
     return tmpBuf.bytes();
+    */
+
+    if (_pathList == NULL) {
+        return NULL;
+    }
+
+    l = _currLink;
+
+    if (l == NULL) {
+        return NULL;
+    }
+
+    componentStruct *c = (componentStruct *) Rp_ChainGetValue(l);
+
+    if (c == NULL) {
+        return NULL;
+    }
+
+    return c->type;
 }
 
@@ -563,5 +704,5 @@
 
     // update the last component from the current path
-    l = Rp_ChainLastLink(_pathList);
+    l = _currLink;
 
     if (l != NULL) {
@@ -571,5 +712,5 @@
         // append the new component onto the current path
         last = new componentStruct;
-        Rp_ChainAppend(_pathList,last);
+        _currLink = Rp_ChainAppend(_pathList,last);
         last->id = NULL;
     }
@@ -593,5 +734,5 @@
     tmpBuf.clear();
 
-    last = Rp_ChainLastLink(_pathList);
+    last = _currLink;
     l = Rp_ChainFirstLink(_pathList);
     while (l != last) {
@@ -685,4 +826,53 @@
 }
 
+size_t
+Path::degree()
+{
+    Rp_ChainLink *l = NULL;
+
+    l = _currLink;
+
+    if (l == NULL) {
+        return 0;
+    }
+
+    componentStruct *c = (componentStruct *) Rp_ChainGetValue(l);
+
+    if (c == NULL) {
+        return 0;
+    }
+
+    return c->degree;
+}
+
+void
+Path::degree(size_t d)
+{
+    if (d == 0) {
+        d = 1;
+    }
+
+    Rp_ChainLink *l = NULL;
+    componentStruct *last = NULL;
+
+    // update the current component from the current path
+    l = _currLink;
+
+    if (l != NULL) {
+        last = (componentStruct *) Rp_ChainGetValue(l);
+    } else {
+        // append the new component onto the current path
+        last = new componentStruct;
+        _currLink = Rp_ChainAppend(_pathList,last);
+    }
+
+    // adjust the degree field
+    last->degree = d;
+
+    __updateBuffer();
+
+    return;
+}
+
 const char *
 Path::path(void)
@@ -696,4 +886,5 @@
     if (p != NULL) {
         _pathList = __parse(p);
+        _currLink = Rp_ChainLastLink(_pathList);
         __updateBuffer();
     }
Index: /trunk/src/objects/RpPath.h
===================================================================
--- /trunk/src/objects/RpPath.h	(revision 1559)
+++ /trunk/src/objects/RpPath.h	(revision 1560)
@@ -48,20 +48,31 @@
     Path& add(const char *el);  // turns input into input.number(blah)
     Path& del();                // turns input.number(blah) into input
+    bool eof();
+
+    Path& first();
+    Path& prev();
+    Path& next();
+    Path& last();
+    size_t count();
 
     // turns input.number(blah) into number(blah)
-    const char *component(void);    // get component of the path
-    void component(const char *p);  // set component of the path
+    const char *component(void);    // get component of the current component
+    void component(const char *p);  // set component of the current component
 
     // turns input.number(blah) into blah
-    const char *id(void);       // get the id of the path
-    void id(const char *p);     // set the id of the path
+    const char *id(void);       // get the id of the current component
+    void id(const char *p);     // set the id of the current component
 
     // turns input.number(blah) into number
-    const char *type(void);     // get the type of the path
-    void type(const char *p);   // set the type of the path
+    const char *type(void);     // get the type of the current component
+    void type(const char *p);   // set the type of the current component
 
     // turns input.number(blah) into input
-    const char *parent(void);   // get the parent of the path
-    void parent(const char *p); // set the parent of the path
+    const char *parent(void);   // get the parent of the current component
+    void parent(const char *p); // set the parent of the current component
+
+    // turns input.number2(blah) into 2
+    size_t degree(void);        // get the degree of the current component
+    void degree(size_t degree); // set the degree of the current component
 
     const char *path(void);     // get the path
@@ -73,4 +84,5 @@
         const char *type;
         const char *id;
+        size_t degree;
     } componentStruct;
 
@@ -80,9 +92,11 @@
     Rp_Chain *__parse(const char *p);
     componentStruct *__createComponent(const char *p, int start,
-                        int end, int idOpenParen, int idCloseParen);
+                        int end, int idOpenParen, int idCloseParen,
+                        size_t degree);
     void __deleteComponent(componentStruct *c);
 
     char _ifs;
     Rp_Chain *_pathList;
+    Rp_ChainLink *_currLink;
     SimpleCharBuffer b;
     SimpleCharBuffer tmpBuf;
Index: /trunk/src/objects/RpPlot.cc
===================================================================
--- /trunk/src/objects/RpPlot.cc	(revision 1559)
+++ /trunk/src/objects/RpPlot.cc	(revision 1560)
@@ -258,5 +258,5 @@
 
 const char *
-Plot::xml()
+Plot::xml(size_t indent, size_t tabstop)
 {
 
@@ -302,5 +302,5 @@
         }
 
-        _tmpBuf.append(c->xml());
+        _tmpBuf.append(c->xml(indent,tabstop));
         _tmpBuf.append("\n",1);
         l = Rp_ChainNextLink(l);
Index: /trunk/src/objects/RpPlot.h
===================================================================
--- /trunk/src/objects/RpPlot.h	(revision 1559)
+++ /trunk/src/objects/RpPlot.h	(revision 1560)
@@ -42,5 +42,5 @@
         Curve *getNthCurve(size_t n) const;
 
-        const char *xml();
+        const char *xml(size_t indent, size_t tabstop);
         const int is() const;
 
Index: /trunk/src/objects/RpScatter.cc
===================================================================
--- /trunk/src/objects/RpScatter.cc	(revision 1559)
+++ /trunk/src/objects/RpScatter.cc	(revision 1560)
@@ -23,4 +23,5 @@
     this->desc("");
     this->group("");
+    propstr("type","scatter");
 }
 
@@ -32,4 +33,5 @@
     this->desc("");
     this->group("");
+    propstr("type","scatter");
 }
 
@@ -42,4 +44,5 @@
     this->desc(desc);
     this->group(group);
+    propstr("type","scatter");
 }
 
@@ -71,6 +74,7 @@
  */
 
+/*
 const char *
-Scatter::xml()
+Scatter::xml(size_t indent, size_t tabstop)
 {
 // FIXME: the xml function should just read an array
@@ -122,4 +126,5 @@
     return _tmpBuf.bytes();
 }
+*/
 
 /**********************************************************************/
Index: /trunk/src/objects/RpScatter.h
===================================================================
--- /trunk/src/objects/RpScatter.h	(revision 1559)
+++ /trunk/src/objects/RpScatter.h	(revision 1560)
@@ -33,5 +33,5 @@
         virtual ~Scatter();
 
-        const char *xml();
+        // const char *xml();
         const int is() const;
 
Index: /trunk/src/objects/RpString.cc
===================================================================
--- /trunk/src/objects/RpString.cc	(revision 1559)
+++ /trunk/src/objects/RpString.cc	(revision 1560)
@@ -78,21 +78,26 @@
 
 const char *
-String::xml()
+String::xml(size_t indent, size_t tabstop)
 {
+    size_t l1width = indent + tabstop;
+    size_t l2width = indent + (2*tabstop);
+    const char *sp = "";
+
     Path p(path());
     _tmpBuf.clear();
 
     _tmpBuf.appendf(
-"<string id='%s'>\n\
-    <about>\n\
-        <label>%s</label>\n\
-        <description>%s</description>\n\
-        <hints>%s</hints>\n\
-    </about>\n\
-    <size>%ix%i</size>\n\
-    <default>%s</default>\n\
-    <current>%s</current>\n\
-</string>\n",
-       p.id(),label(),desc(),hints(),width(),height(),def(),cur());
+"%12$*9$s<string id='%1$s'>\n\
+%12$*10$s<about>\n\
+%12$*11$s<label>%2$s</label>\n\
+%12$*11$s<description>%3$s</description>\n\
+%12$*11$s<hints>%4$s</hints>\n\
+%12$*10$s</about>\n\
+%12$*10$s<size>%5$ix%6$i</size>\n\
+%12$*10$s<default>%7$s</default>\n\
+%12$*10$s<current>%8$s</current>\n\
+%12$*9$s</string>\n",
+       p.id(),label(),desc(),hints(),width(),height(),def(),cur(),
+       indent, l1width, l2width, sp);
 
     return _tmpBuf.bytes();
Index: /trunk/src/objects/RpString.h
===================================================================
--- /trunk/src/objects/RpString.h	(revision 1559)
+++ /trunk/src/objects/RpString.h	(revision 1560)
@@ -39,5 +39,5 @@
     Accessor<size_t> height;
 
-    const char *xml();
+    const char *xml(size_t indent, size_t tabstop);
     const int is() const;
 
Index: /trunk/src/objects/RpTree.c
===================================================================
--- /trunk/src/objects/RpTree.c	(revision 1559)
+++ /trunk/src/objects/RpTree.c	(revision 1560)
@@ -220,5 +220,5 @@
  */
 static Node *
-NewNode(TreeObject *treeObjPtr, CONST char *name, int inode)
+NewNode(TreeObject *treeObjPtr, CONST char *name, size_t inode)
 {
     Node *nodePtr;
@@ -840,5 +840,5 @@
     Node *nodePtr;  /* Node to be inserted. */
     TreeObject *treeObjPtr;
-    int inode;
+    size_t inode;
     int isNew;
 
@@ -890,5 +890,5 @@
                              * be inserted. */
     CONST char *name,       /* Name of node. */
-    int inode,              /* Requested id of the new node. If a
+    size_t inode,           /* Requested id of the new node. If a
                              * node by this id already exists in the
                              * tree, no node is created. */
@@ -1004,5 +1004,5 @@
 
 Rp_TreeNode
-Rp_TreeGetNode(TreeClient *clientPtr, unsigned int inode)
+Rp_TreeGetNode(TreeClient *clientPtr, size_t inode)
 {
     TreeObject *treeObjPtr = clientPtr->treeObject;
@@ -1099,4 +1099,32 @@
     label = Rp_TreeGetKey(string);
     for (nodePtr = parentPtr->first; nodePtr != NULL; nodePtr = nodePtr->next) {
+        if (label == nodePtr->label) {
+            return nodePtr;
+        }
+    }
+    return NULL;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Rp_TreeFindChildNext --
+ *
+ *  Searches for the next named node in a parent's chain of siblings.
+ *
+ *
+ * Results:
+ *  If found, the child node is returned, otherwise NULL.
+ *
+ *----------------------------------------------------------------------
+ */
+Rp_TreeNode
+Rp_TreeFindChildNext(Node *childPtr, CONST char *string)
+{
+    Rp_TreeKey label;
+    register Node *nodePtr;
+
+    label = Rp_TreeGetKey(string);
+    for (nodePtr = childPtr->next; nodePtr != NULL; nodePtr = nodePtr->next) {
         if (label == nodePtr->label) {
             return nodePtr;
@@ -1481,4 +1509,8 @@
 }
 
+/*
+ * commented out to avoid compiler warnings about function not being used
+ */
+/*
 static int
 ParseParentheses(
@@ -1487,6 +1519,7 @@
     char **rightPtr)
 {
-    register char *p;
-    char *left, *right;
+    register char *p = NULL;
+    char *left = NULL;
+    char *right = NULL;
 
     left = right = NULL;
@@ -1510,101 +1543,108 @@
     return RP_OK;
 }
+*/
 
 //FIXME: commented out because it calls Rp_TreeGetArrayValue
-//int
-//Rp_TreeGetValue(
-//    TreeClient *clientPtr,
-//    Node *nodePtr,
-//    CONST char *string,     /* String identifying the field in node. */
-//    void **objPtrPtr)
-//{
-//    char *left, *right;
-//    int result;
-//
+int
+Rp_TreeGetValue(
+    TreeClient *clientPtr,
+    Node *nodePtr,
+    CONST char *string,     /* String identifying the field in node. */
+    void **objPtrPtr)
+{
+    char *left = NULL;
+    char *right = NULL;
+    int result;
+
+// uncomment after Rp_TreeGetArrayValue is fixed
 //    if (ParseParentheses(string, &left, &right) != TCL_OK) {
 //        return TCL_ERROR;
 //    }
-//    if (left != NULL) {
-//        *left = *right = '\0';
-//        result = Rp_TreeGetArrayValue(clientPtr, nodePtr, string, left + 1, objPtrPtr);
-//        *left = '(', *right = ')';
-//    } else {
-//        result = Rp_TreeGetValueByKey(clientPtr, nodePtr,
-//                    Rp_TreeGetKey(string), objPtrPtr);
-//    }
-//    return result;
-//}
+    if (left != NULL) {
+        *left = *right = '\0';
+        // result = Rp_TreeGetArrayValue(clientPtr, nodePtr, string, left + 1, objPtrPtr);
+        *left = '(', *right = ')';
+    } else {
+        result = Rp_TreeGetValueByKey(clientPtr, nodePtr,
+                    Rp_TreeGetKey(string), objPtrPtr);
+    }
+    return result;
+}
 
 //FIXME: commented out because it calls Rp_TreeSetArrayValue
-//int
-//Rp_TreeSetValue(
-//    TreeClient *clientPtr,
-//    Node *nodePtr,          /* Node to be updated. */
-//    CONST char *string,     /* String identifying the field in node. */
-//    void *valueObjPtr)      /* New value of field. If NULL, field
-//                             * is deleted. */
-//{
-//    char *left, *right;
-//    int result;
-//
+int
+Rp_TreeSetValue(
+    TreeClient *clientPtr,
+    Node *nodePtr,          /* Node to be updated. */
+    CONST char *string,     /* String identifying the field in node. */
+    void *valueObjPtr)      /* New value of field. If NULL, field
+                             * is deleted. */
+{
+    char *left = NULL;
+    char *right = NULL;
+    int result;
+
+// uncomment after Rp_TreeSetArrayValue is fixed
 //    if (ParseParentheses(string, &left, &right) != RP_OK) {
 //        return RP_ERROR;
 //    }
-//    if (left != NULL) {
-//        *left = *right = '\0';
-//        result = Rp_TreeSetArrayValue(clientPtr, nodePtr, string, left + 1, valueObjPtr);
-//        fprintf(stderr, "Rp_TreeSetArrayValue not supported\n", name);
-//
-//        *left = '(', *right = ')';
-//    } else {
-//        result = Rp_TreeSetValueByKey(clientPtr, nodePtr,
-//                    Rp_TreeGetKey(string), valueObjPtr);
-//    }
-//    return result;
-//}
+    if (left != NULL) {
+        *left = *right = '\0';
+        //result = Rp_TreeSetArrayValue(clientPtr, nodePtr, string, left + 1, valueObjPtr);
+        *left = '(', *right = ')';
+    } else {
+        result = Rp_TreeSetValueByKey(clientPtr, nodePtr,
+                    Rp_TreeGetKey(string), valueObjPtr);
+    }
+    return result;
+}
 
 //FIXME: commented out because it calls Rp_TreeUnsetArrayValue
-//int
-//Rp_TreeUnsetValue(
-//    TreeClient *clientPtr,
-//    Node *nodePtr,          /* Node to be updated. */
-//    CONST char *string)     /* String identifying the field in node. */
-//{
-//    char *left, *right;
-//    int result;
-//
+int
+Rp_TreeUnsetValue(
+    TreeClient *clientPtr,
+    Node *nodePtr,          /* Node to be updated. */
+    CONST char *string)     /* String identifying the field in node. */
+{
+    char *left = NULL;
+    char *right = NULL;
+    int result;
+
+// uncomment after Rp_TreeUnsetArrayValue is fixed
 //    if (ParseParentheses(string, &left, &right) != RP_OK) {
 //        return RP_ERROR;
 //    }
-//    if (left != NULL) {
-//        *left = *right = '\0';
-//        result = Rp_TreeUnsetArrayValue(clientPtr, nodePtr, string, left + 1);
-//        *left = '(', *right = ')';
-//    } else {
-//        result = Rp_TreeUnsetValueByKey(clientPtr, nodePtr, Rp_TreeGetKey(string));
-//    }
-//    return result;
-//}
+    if (left != NULL) {
+        *left = *right = '\0';
+        // result = Rp_TreeUnsetArrayValue(clientPtr, nodePtr, string, left + 1);
+        *left = '(', *right = ')';
+    } else {
+        result = Rp_TreeUnsetValueByKey(clientPtr, nodePtr, Rp_TreeGetKey(string));
+    }
+    return result;
+}
 
 //FIXME: commented out because it calls Rp_TreeArrayValueExists
-//int
-//Rp_TreeValueExists(TreeClient *clientPtr, Node *nodePtr, CONST char *string)
-//{
-//    char *left, *right;
-//    int result;
-//
+int
+Rp_TreeValueExists(TreeClient *clientPtr, Node *nodePtr, CONST char *string)
+{
+    char *left = NULL;
+    char *right = NULL;
+    int result;
+
+// uncomment after Rp_TreeArrayValueExists is fixed
 //    if (ParseParentheses(string, &left, &right) != RP_OK) {
 //        return FALSE;
 //    }
-//    if (left != NULL) {
-//        *left = *right = '\0';
-//        result = Rp_TreeArrayValueExists(clientPtr, nodePtr, string, left + 1);
-//        *left = '(', *right = ')';
-//    } else {
-//        result = Rp_TreeValueExistsByKey(clientPtr, nodePtr,
-//                Rp_TreeGetKey(string));
-//    }
-//    return result;
-//}
+    if (left != NULL) {
+        *left = *right = '\0';
+        // result = Rp_TreeArrayValueExists(clientPtr, nodePtr, string, left + 1);
+        *left = '(', *right = ')';
+    } else {
+        result = Rp_TreeValueExistsByKey(clientPtr, nodePtr,
+                Rp_TreeGetKey(string));
+    }
+    return result;
+}
 
 Rp_TreeKey
@@ -1955,4 +1995,32 @@
 //    return RP_OK;
 //}
+
+int
+Rp_TreeGetTokenFromToken(
+    TreeClient *fromClientPtr, // old client from which to base the new client
+    TreeClient **clientPtrPtr) // new client
+{
+    TreeClient *clientPtr;
+    TreeObject *treeObjPtr;
+
+    if (fromClientPtr == NULL) {
+        fprintf(stderr, "can't create new token from null token\n");
+        return RP_ERROR;
+    }
+
+    treeObjPtr = fromClientPtr->treeObject;
+    if (treeObjPtr == NULL) {
+        fprintf(stderr, "can't find a tree object based on provided client\n");
+        return RP_ERROR;
+    }
+    clientPtr = NewTreeClient(treeObjPtr);
+    if (clientPtr == NULL) {
+        fprintf(stderr, "can't allocate token for tree \"%s\"",
+            treeObjPtr->name);
+        return RP_ERROR;
+    }
+    *clientPtrPtr = clientPtr;
+    return RP_OK;
+}
 
 void
@@ -3031,5 +3099,5 @@
             RebuildTable(nodePtr);
         }
-        } else {
+    } else {
         Value *prevPtr;
 
Index: /trunk/src/objects/RpTree.h
===================================================================
--- /trunk/src/objects/RpTree.h	(revision 1559)
+++ /trunk/src/objects/RpTree.h	(revision 1560)
@@ -192,5 +192,6 @@
 
     unsigned int nChildren; /* # of children for this node. */
-    unsigned int inode;     /* Serial number of the node. */
+    // unsigned int inode;     /* Serial number of the node. */
+    size_t inode;           /* Serial number of the node. */
 
     unsigned short depth;   /* The depth of this node in the tree. */
@@ -281,5 +282,5 @@
         Rp_TreeNode parent, CONST char *name, int position));
 EXTERN Rp_TreeNode Rp_TreeCreateNodeWithId _ANSI_ARGS_((Rp_Tree tree,
-        Rp_TreeNode parent, CONST char *name, int position, int inode));
+        Rp_TreeNode parent, CONST char *name, size_t inode, int position));
 
 EXTERN int Rp_TreeDeleteNode _ANSI_ARGS_((Rp_Tree tree, Rp_TreeNode node));
@@ -288,8 +289,10 @@
         Rp_TreeNode parent, Rp_TreeNode before));
 
-EXTERN Rp_TreeNode Rp_TreeGetNode _ANSI_ARGS_((Rp_Tree tree,
-        unsigned int inode));
+EXTERN Rp_TreeNode Rp_TreeGetNode _ANSI_ARGS_((Rp_Tree tree, size_t inode));
 
 EXTERN Rp_TreeNode Rp_TreeFindChild _ANSI_ARGS_((Rp_TreeNode parent,
+        CONST char *name));
+
+EXTERN Rp_TreeNode Rp_TreeFindChildNext _ANSI_ARGS_((Rp_TreeNode child,
         CONST char *name));
 
@@ -391,4 +394,7 @@
         Rp_TreeApplyProc *proc, ClientData clientData));
 
+EXTERN int Rp_TreeApplyXML _ANSI_ARGS_((Rp_TreeNode root,
+        Rp_TreeApplyProc *proc, ClientData clientData));
+
 EXTERN int Rp_TreeSortNode _ANSI_ARGS_((Rp_Tree tree, Rp_TreeNode node,
         Rp_TreeCompareNodesProc *proc));
@@ -399,6 +405,9 @@
 // EXTERN int Rp_TreeExists _ANSI_ARGS_((CONST char *name));
 
-EXTERN int Rp_TreeGetToken _ANSI_ARGS_((CONST char *name,
-        Rp_Tree *treePtr));
+// EXTERN int Rp_TreeGetToken _ANSI_ARGS_((CONST char *name,
+//         Rp_Tree *treePtr));
+
+EXTERN int Rp_TreeGetTokenFromToken _ANSI_ARGS_((
+        CONST Rp_Tree tree, Rp_Tree *newToken));
 
 EXTERN void Rp_TreeReleaseToken _ANSI_ARGS_((Rp_Tree tree));
