 +        $this->encoding,
 +        str_replace("\n", "\n  ", xp::stringOf($this->root))
 +      );
-+    }
+     }
+-
+-    /**
+-     * Callback function for XMLParser
+-     *
+-     * @param   resource parser
+-     * @param   string cdata
+-     * @see     xp://xml.parser.XMLParser
+-     */
+-    public function onCData($parser, $cdata) {
+-      $this->_cdata.= $cdata;
+-    }
+-
+-    /**
+-     * Callback function for XMLParser
+-     *
+-     * @param   resource parser
+-     * @param   string data
+-     * @see     xp://xml.parser.XMLParser
+-     */
+-    public function onDefault($parser, $data) {
+-    }
    } 
  ?>
 Index: skeleton/xml/parser/TreeParser.class.php
 ===================================================================
 --- skeleton/xml/parser/TreeParser.class.php	(revision 0)
 +++ skeleton/xml/parser/TreeParser.class.php	(revision 0)
-@@ -0,0 +1,112 @@
+@@ -0,0 +1,132 @@
 +<?php
 +/* This class is part of the XP framework
 + *

      * @param   io.File file
      * @param   string c default __CLASS__ class name
      * @return  xml.Tree
@@ -165,70 +165,73 @@
     /**
      * Callback function for XMLParser
      *
+     * @deprecated Use xml.parser.TreeParser instead
      * @param   resource parser
      * @param   string name
      * @param   string attrs
      * @see     xp://xml.parser.XMLParser
      */
     public function onStartElement($parser, $name, $attrs) {
-      $this->_cdata= '';
-
-      $element= new $this->nodeType($name, NULL, $attrs);
-      if (!isset($this->_cnt)) {
-        $this->root= $element;

+     * @see     xp://xml.parser.XMLParser
+     */
+    public function onCData($parser, $cdata) {
+
+      // Ignore tokens consisting entirely of whitespace
+      if (strlen($cdata) !== strspn($cdata, " \r\n\t")) {
+        $this->stack[0]->addChild(new Text($cdata));
+      }
+    }
+
+    /**
