function parseXML(text) {
      var list = String.prototype.split.call(text, /<([^!<>?](?:'[\S\s]*?'|"[\S\s]*?"|[^'"<>])*|!(?:--[\S\s]*?--|\[[^\[\]'"<>]+\[[\S\s]*?]]|DOCTYPE[^\[<>]*?\[[\S\s]*?]|(?:ENTITY[^"<>]*?"[\S\s]*?")?[\S\s]*?)|\?[\S\s]*?\?)>/);
      var length = list.length;

      // root element
      var root = {f: []};
      var elem = root;

      // dom tree stack
      var stack = [];

      for (var i = 0; i < length;) {
        // text node
        var str = list[i++];
        if (str) appendText(str);

        // child node
        var tag = list[i++];
        if (tag) parseNode(tag);
      }

      return root;

      function parseNode(tag) {
        var tagLength = tag.length;
        var firstChar = tag[0];
        if (firstChar === '/') {
          // close tag
          var closed = tag.replace(/^\/|[\s\/].*$/g, '').toLowerCase();
          while (stack.length) {
            var tagName = elem.n && elem.n.toLowerCase();
            elem = stack.pop();
            if (tagName === closed) break;
          }
        // } else if (firstChar === "?") {
        //   // XML declaration
        //   appendChild({n: "?", r: tag.substr(1, tagLength - 2)});
        } else if (firstChar === '!') {
          if (tag.substr(1, 7) === '[CDATA[' && tag.substr(-2) === ']]') {
            // CDATA section
            appendText(tag.substr(8, tagLength - 10));
          } else {
            // comment
            appendChild({n: '!', r: tag.substr(1)});
          }
        } else {
          var child = openTag(tag);
          appendChild(child);
          if (tag[tagLength - 1] === '/') {
            child.c = 1; // emptyTag
          } else {
            stack.push(elem); // openTag
            elem = child;
          }
        }
      }

      function appendChild(child) {
        elem.f.push(child);
      }

      function appendText(str) {
        str = removeSpaces(str);
        if (str) appendChild(unescapeXML(str));
      }
    }
The fromXML() method parses an XML string, constructing the JavaScript
value or object described by the string.

@function fromXML
@param text {String} The string to parse as XML
@param [reviver] {Function} If a function, prescribes how the value
originally produced by parsing is transformed, before being returned.
@returns {Object}