/*     ESPX - an ECMAScript Parser for (almost) XML, with namespaces
  Version 20020313
  Copyright (c) 2000, 2001, 2002 Cyril Jandia

  Permission is hereby granted, free of charge, to any person obtaining
  a copy of this software and associated documentation files (the
  ``Software''), to deal in the Software without restriction, including
  without limitation the rights to use, copy, modify, merge, publish,
  distribute, sublicense, and/or sell copies of the Software, and to
  permit persons to whom the Software is furnished to do so, subject to
  the following conditions:

  The above copyright notice and this permission notice shall be included
  in all copies or substantial portions of the Software.

  THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
  OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
  IN NO EVENT SHALL CYRIL JANDIA BE LIABLE FOR ANY CLAIM, DAMAGES OR
  OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
  ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
  OTHER DEALINGS IN THE SOFTWARE.

  Except as contained in this notice, the name of Cyril Jandia shall not
  be used in advertising or otherwise to promote the sale, use or other
  dealings in this Software without prior written authorization from
  Cyril Jandia. */

//  XMLDocument
//  private
      XMLDocument.prototype._ents = "";
      XMLDocument.prototype._ns = null;
      XMLDocument.prototype._all = null;
      XMLDocument.prototype._id = 0;
      XMLDocument.prototype._lastId = 0;
      XMLDocument.prototype._lastEI = 0;
      XMLDocument.prototype._elts = null;
      XMLDocument.prototype._hasXMLDecl = false;
      XMLDocument.prototype._setNodeName = XMLDocument_setNodeName; // provision for perf. improvements; currently, simply: "node.nodeName = name"
      XMLDocument.prototype._addChild = XMLNode_addChild;
//  public
      XMLDocument.prototype.index = -1;
      XMLDocument.prototype.nodeName = "#document";
      XMLDocument.prototype.nodeValue = null; // always (same as in the DOM)
      XMLDocument.prototype.nodeType = 9;
      XMLDocument.prototype.parentNode = null; // always (same as in the DOM)
      XMLDocument.prototype.childCount = 0;
      XMLDocument.prototype.previousSibling = null; // always (of course)
      XMLDocument.prototype.nextSibling = null; // always (of course)
      XMLDocument.prototype.ownerDocument = null; // always (same as in the DOM)
      XMLDocument.prototype.doctype = null; // maybe one day we'll support this
      XMLDocument.prototype.documentElement = null;
      XMLDocument.prototype.factory = null;
      XMLDocument.prototype.namespaces = XMLDocument_namespaces;
      XMLDocument.prototype.all = XMLDocument_all;
      XMLDocument.prototype.createComment = XMLDocument_createComment;
      XMLDocument.prototype.createProcessingInstruction = XMLDocument_createProcessingInstruction;
      XMLDocument.prototype.createElement = XMLDocument_createElement;
      XMLDocument.prototype.createTextNode = XMLDocument_createTextNode;
      XMLDocument.prototype.createCDATASection = XMLDocument_createCDATASection;
      XMLDocument.prototype.getElementsByTagName = XMLDocument_getElementsByTagName;
      XMLDocument.prototype.getFirstChildNamed = XMLContainer_getFirstChildNamed;
      XMLDocument.prototype.uniqueID = XMLNode_uniqueID;
      XMLDocument.prototype.isLast = XMLDocument_isLast;
      XMLDocument.prototype.xmlText = XMLNode_xmlText;
//  end - XMLDocument

//  XMLElement
//  private
      XMLElement.prototype._ns = null;
      XMLElement.prototype._nsi = 0;
      XMLElement.prototype._id = 0;
      XMLElement.prototype._attlist = ""; // specified attributes
      XMLElement.prototype._xmlspace = false; // was xml:space specified ?
      XMLElement.prototype._xmllang = false; // and xml:lang ?
      XMLElement.prototype._xmlbase = false; // and xml:base ?
      XMLElement.prototype._opened = false;
      XMLElement.prototype._closed = false;
      XMLElement.prototype._addChild = XMLNode_addChild;
//  public
      XMLElement.prototype.index = 0;
      XMLElement.prototype.nodeName = null;
      XMLElement.prototype.nodeValue = null; // always (same as in the DOM)
      XMLElement.prototype.nodeType = 1;
      XMLElement.prototype.parentNode = null;
      XMLElement.prototype.childCount = 0;
      XMLElement.prototype.previousSibling = null;
      XMLElement.prototype.nextSibling = null;
      XMLElement.prototype.ownerDocument = null;
      XMLElement.prototype.attributes = null;
      XMLElement.prototype.namespacePrefixes = XMLElement_namespacePrefixes;
      XMLElement.prototype.namespaceURI = XMLElement_namespaceURI;
      XMLElement.prototype.named = XMLElement_named;
      XMLElement.prototype.getAttribute = XMLElement_getAttribute;
      XMLElement.prototype.setAttribute = XMLElement_setAttribute;
      XMLElement.prototype.getFirstChildNamed = XMLContainer_getFirstChildNamed;
      XMLElement.prototype.uniqueID = XMLNode_uniqueID;
      XMLElement.prototype.isLast = XMLNode_isLast;
      XMLElement.prototype.xmlText = XMLNode_xmlText;
//  end - XMLElement

//  XMLText
//  public
      XMLText.prototype._id = 0;
      XMLText.prototype.index = 0;
      XMLText.prototype.nodeName = "#text";
      XMLText.prototype.nodeValue = null;
      XMLText.prototype.nodeType = 3;
      XMLText.prototype.parentNode = null;
      XMLText.prototype.childCount = 0; // always
      XMLText.prototype.previousSibling = null;
      XMLText.prototype.nextSibling = null;
      XMLText.prototype.ownerDocument = null;
      XMLText.prototype.uniqueID = XMLNode_uniqueID;
      XMLText.prototype.isLast = XMLNode_isLast;
      XMLText.prototype.xmlText = XMLNode_xmlText;
//  end - XMLText

//  XMLCDATASection
//  public
      XMLCDATASection.prototype._id = 0;
      XMLCDATASection.prototype.index = 0;
      XMLCDATASection.prototype.nodeName = "#cdata-section";
      XMLCDATASection.prototype.nodeValue = null;
      XMLCDATASection.prototype.nodeType = 4;
      XMLCDATASection.prototype.parentNode = null;
      XMLCDATASection.prototype.childCount = 0; // always
      XMLCDATASection.prototype.previousSibling = null;
      XMLCDATASection.prototype.nextSibling = null;
      XMLCDATASection.prototype.ownerDocument = null;
      XMLCDATASection.prototype.uniqueID = XMLNode_uniqueID;
      XMLCDATASection.prototype.isLast = XMLNode_isLast;
      XMLCDATASection.prototype.xmlText = XMLNode_xmlText;
//  end - XMLCDATASection

//  XMLProcessingInstruction
//  public
      XMLProcessingInstruction.prototype._id = 0;
      XMLProcessingInstruction.prototype.index = 0;
      XMLProcessingInstruction.prototype.nodeName = null;
      XMLProcessingInstruction.prototype.nodeValue = null;
      XMLProcessingInstruction.prototype.nodeType = 7;
      XMLProcessingInstruction.prototype.parentNode = null;
      XMLProcessingInstruction.prototype.childCount = 0; // always
      XMLProcessingInstruction.prototype.previousSibling = null;
      XMLProcessingInstruction.prototype.nextSibling = null;
      XMLProcessingInstruction.prototype.ownerDocument = null;
      XMLProcessingInstruction.prototype.uniqueID = XMLNode_uniqueID;
      XMLProcessingInstruction.prototype.isLast = XMLNode_isLast;
      XMLProcessingInstruction.prototype.xmlText = XMLNode_xmlText;
//  end - XMLProcessingInstruction

//  XMLComment
//  public
      XMLComment.prototype._id = 0;
      XMLComment.prototype.index = 0;
      XMLComment.prototype.nodeName = "#comment";
      XMLComment.prototype.nodeValue = null;
      XMLComment.prototype.nodeType = 8;
      XMLComment.prototype.parentNode = null;
      XMLComment.prototype.childCount = 0; // always
      XMLComment.prototype.previousSibling = null;
      XMLComment.prototype.nextSibling = null;
      XMLComment.prototype.ownerDocument = null;
      XMLComment.prototype.uniqueID = XMLNode_uniqueID;
      XMLComment.prototype.isLast = XMLNode_isLast;
      XMLComment.prototype.xmlText = XMLNode_xmlText;
//  end - XMLComment

//  XMLDocumentFactory - also plays a role similar to that of DOMImplementation
//  (see http://www.w3.org/TR/REC-DOM-Level-1/)
//  public
      XMLDocumentFactory.prototype.parser = null;
      XMLDocumentFactory.prototype.hasFeature = XMLDocumentFactory_hasFeature;
      XMLDocumentFactory.prototype.createDocument = XMLDocumentFactory_createDocument;
//  end - XMLDocumentFactory

//  XMLParser
//  private
      XMLParser.prototype._factory = null;
      XMLParser.prototype._input = null;
      XMLParser.prototype._pos = 0;
      XMLParser.prototype._end = 0;
      XMLParser.prototype._line = 1;
      XMLParser.prototype._column = 1;
      // parse stack implementation
      XMLParser.prototype._tos = -1; // cursor for top of parse stack
      XMLParser.prototype._last = null; // node at top of parse stack
      XMLParser.prototype._seenXMLDecl = false;
      XMLParser.prototype._push = XMLParser_stack_push;
      XMLParser.prototype._pop = XMLParser_stack_pop;
      // new parse init
      XMLParser.prototype._init = XMLParser_init;
      // getting the job done
      XMLParser.prototype._lookForInvalidCharacters = XMLParser_lookForInvalidCharacters;
      XMLParser.prototype._doParse = XMLParser_doParse;
      // input eating
      XMLParser.prototype._shiftTo = XMLParser_shiftTo;
      // the parsing proper; utilities first
      XMLParser.prototype._prepareDoc = XMLParser_prepareDoc;
      XMLParser.prototype._eof = XMLParser_eof;
      XMLParser.prototype._skipBlanks = XMLParser_skipBlanks;
      XMLParser.prototype._hasNonWhiteSpace = XMLParser_hasNonWhiteSpace;
      // the parsing proper; XML syntax handling
      XMLParser.prototype._isXMLDecl = XMLParser_isXMLDecl;
      XMLParser.prototype._isComment = XMLParser_isComment;
      XMLParser.prototype._isPI = XMLParser_isPI;
      XMLParser.prototype._isDocTypeDecl = XMLParser_isDocTypeDecl;
      XMLParser.prototype._isCDATASection = XMLParser_isCDATASection;
      XMLParser.prototype._isNamePos = XMLParser_isNamePos;
      XMLParser.prototype._parseProlog = XMLParser_parseProlog;
      XMLParser.prototype._parseXMLDecl = XMLParser_parseXMLDecl;
      XMLParser.prototype._parseMisc = XMLParser_parseMisc;
      XMLParser.prototype._parseDocTypeDecl = XMLParser_parseDocTypeDecl;
      XMLParser.prototype._parseComment = XMLParser_parseComment;
      XMLParser.prototype._parsePI = XMLParser_parsePI;
      XMLParser.prototype._parseRoot = XMLParser_parseRoot;
      XMLParser.prototype._parseElement = XMLParser_parseElement;
      XMLParser.prototype._parseAttr = XMLParser_parseAttr;
      XMLParser.prototype._nsHandling = XMLParser_nsHandling;
      XMLParser.prototype._nsDeclaration = XMLParser_nsDeclaration;
      XMLParser.prototype._nsScoping = XMLParser_nsScoping;
      XMLParser.prototype._nsValidation = XMLParser_nsValidation;
      XMLParser.prototype._parseText = XMLParser_parseText;
      XMLParser.prototype._parseCDATASection = XMLParser_parseCDATASection;
      // error handling
      XMLParser.prototype._messages = null;
      XMLParser.prototype._raiseError = XMLParser_raiseError;
//  public
      XMLParser.prototype.namespaceAware = true;
      XMLParser.prototype.xmlLang = "";
      XMLParser.prototype.xmlBase = "";
      XMLParser.prototype.document = null;
      XMLParser.prototype.documentTypeName = null;
      XMLParser.prototype.parseError = null;
      XMLParser.prototype.preserveWhiteSpace = false;
      XMLParser.prototype.parse = XMLParser_parse;
      XMLParser.prototype.getVersion = XMLParser_getVersion;
//  end - XMLParser

//  XMLParseError
//  public
      XMLParseError.prototype.parser = null;
      XMLParseError.prototype.code = 0;
      XMLParseError.prototype.line = 0;
      XMLParseError.prototype.column = 0;
      XMLParseError.prototype.message = null;
//  end - XMLParseError


/////////////////////////////////////////////////////////////////////////////
//  Implementation  /////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////

var __espx_version_number = 20020313;

//  Bad news first, as usual ...

var XMLPARSER_INVALID_XMLDECL_ERR         = 1;
var XMLPARSER_UNSUPPORTED_XMLVERSION_ERR  = 2;
var XMLPARSER_UNSUPPORTED_DOCTYPEDECL_ERR = 3;
var XMLPARSER_ILLFORMED_DOCUMENT_ERR      = 4;
var XMLPARSER_BAD_COMMENT_ERR             = 5;
var XMLPARSER_BAD_PI_ERR                  = 6;
var XMLPARSER_INVALID_PITARGET_ERR        = 7;
var XMLPARSER_INCORRECT_XMLDECLPOS_ERR    = 8;
var XMLPARSER_RESERVED_XMLNAME_ERR        = 9;
var XMLPARSER_BAD_ETAG_ERR                = 10;
var XMLPARSER_UNEXPECTED_CHAR_ERR         = 11;
var XMLPARSER_BAD_STAG_ERR                = 12;
var XMLPARSER_DUPLICATE_ATTRIBUTE_ERR     = 13;
var XMLPARSER_MISSING_EQSIGN_ERR          = 14;
var XMLPARSER_BAD_ATTDELIM_ERR            = 15;
var XMLPARSER_ILLEGAL_XMLSPACEATTR_ERR    = 16;
var XMLPARSER_UNMATCHED_ATTDELIM_ERR      = 17;
var XMLPARSER_BAD_ENTITYREF_ERR           = 18;
var XMLPARSER_BAD_NSURI_ERR               = 19;
var XMLPARSER_NO_NSINSCOPE_ERR            = 20;
var XMLPARSER_BAD_DOCTYPEDECL_ERR         = 21;
var XMLPARSER_INVALID_CHAR_ERR            = 22;
var XMLPARSER_BAD_DOCTYPENAME_ERR         = 23;

// Predefined entities

var __entities = {
// Latin-1
"nbsp":160,"iexcl":161,"cent":162,"pound":163,"curren":164,"yen":165,"brvbar":166,"sect":167,
"uml":168,"copy":169,"ordf":170,"laquo":171,"not":172,"shy":173,"reg":174,"macr":175,
"deg":176,"plusmn":177,"sup2":178,"sup3":179,"acute":180,"micro":181,"para":182,"middot":183,
"cedil":184,"sup1":185,"ordm":186,"raquo":187,"frac14":188,"frac12":189,"frac34":190,"iquest":191,
"Agrave":192,"Aacute":193,"Acirc":194,"Atilde":195,"Auml":196,"Aring":197,"AElig":198,"Ccedil":199,
"Egrave":200,"Eacute":201,"Ecirc":202,"Euml":203,"Igrave":204,"Iacute":205,"Icirc":206,"Iuml":207,
"ETH":208,"Ntilde":209,"Ograve":210,"Oacute":211,"Ocirc":212,"Otilde":213,"Ouml":214,"times":215,
"Oslash":216,"Ugrave":217,"Uacute":218,"Ucirc":219,"Uuml":220,"Yacute":221,"THORN":222,"szlig":223,
"agrave":224,"aacute":225,"acirc":226,"atilde":227,"auml":228,"aring":229,"aelig":230,"ccedil":231,
"egrave":232,"eacute":233,"ecirc":234,"euml":235,"igrave":236,"iacute":237,"icirc":238,"iuml":239,
"eth":240,"ntilde":241,"ograve":242,"oacute":243,"ocirc":244,"otilde":245,"ouml":246,"divide":247,
"oslash":248,"ugrave":249,"uacute":250,"ucirc":251,"uuml":252,"yacute":253,"thorn":254,"yuml":255,
// Symbols
"fnof":402,"bull":8226,"hellip":8230,"trade":8482,
// Special
"OElig":338,"oelig":339,"Scaron":352,"scaron":353,"Yuml":376,"circ":710,"tilde":732,"ensp":8194,
"emsp":8195,"thinsp":8201,"zwnj":8204,"zwj":8205,"lrm":8206,"rlm":8207,"ndash":8211,"mdash":8212,
"lsquo":8216,"rsquo":8217,"sbquo":8218,"ldquo":8220,"rdquo":8221,"bdquo":8222,"dagger":8224,"Dagger":8225,
"permil":8240,"lsaquo":8249,"rsaquo":8250,"euro":8364
};

//  XMLNode

function XMLNode_addChild(node) {
  var ns;
  if(this.childCount) {
    this[this.childCount - 1].nextSibling = node;
    node.previousSibling = this[this.childCount - 1];
    node.index = this.childCount;
  }
  this[this.childCount++] = node;
  node.parentNode = this;
  if(node.nodeType == 1)
    if(this.nodeType == 1)
      for(ns in this._ns)
        node._ns[ns] = this._ns[ns];
    else
      node._ns["$"] = 0; // null default namespace is the default for root element (unless overriden by xmlns='...')
}

function XMLNode_uniqueID() {
  return ( (this.nodeType == 1) ? ("ESPXID_E" + this._id.toString()) : ("ESPX_N" + this._id.toString()) );
}

function XMLNode_isLast(ofType) {
  var result = true, node = this.nextSibling, t;
  while(result && node) {
    t = node.nodeType;
    if(t == 4)
      t = 3;
    result = (t != ofType);
    node = node.nextSibling;
  }
  return ( result );
}

function XMLNode_xmlText() {
  var result, p, a, v, i, c;
  var re_amp = /\&/gi;
  var re_lt = /\</gi;
  var re_quot = /\"/gi;
  result = "";
  if(this.nodeType == 1) {
    result = "<" + this.nodeName;
    for(p in this.attributes) {
      a = p.substring(1, p.length);
      v = this.attributes[p];
      v = v.replace(re_amp, "&amp;");
      v = v.replace(re_lt, "&lt;");
      v = v.replace(re_quot, "&quot;");
      c = a.indexOf(":");
      if((c > 0) && (a.substring(0, c) != "xml") && (this._ns["$" + a.substring(0, c)] == 1))
        continue;
      if((a=="xml:space")&&this._xmlspace&&((this.parentNode.nodeType==9) ||
        (v!=this.parentNode.getAttribute("xml:space"))))
        result+=" "+a+"=\""+v+"\"";
      else if((a=="xml:lang")&&this._xmllang&&((this.parentNode.nodeType==9)||(v!=this.parentNode.getAttribute("xml:lang"))))
        result+=" "+a+"=\""+v+"\"";
      else if((a=="xml:base")&&this._xmlbase&&((this.parentNode.nodeType==9)||(v!=this.parentNode.getAttribute("xml:base"))))
        result+=" "+a+"=\""+v+"\"";
      else if((a!="xml:space")&&(a!="xml:lang")&&(a!="xml:base"))
        result+=" "+a+"=\""+v+"\"";
    }
    if(this.childCount) {
      result += ">";
      for(i = 0; i < this.childCount; i++)
        result += this[i].xmlText();
      result += "</" + this.nodeName + ">";
    } else
      result += "/>";
    if(this.parentNode.nodeType == 9)
      result += "\n";
  }
  else if(this.nodeType == 3)
    result = this.nodeValue.replace(re_amp, "&amp;").replace(re_lt, "&lt;");
  else if(this.nodeType == 4)
    result = "<![CDATA[" + this.nodeValue + "]]>";
  else if(this.nodeType == 7) {
    result = "<?" + this.nodeName + " " + this.nodeValue + "?>";
    if(this.parentNode.nodeType == 9)
      result += "\n";
  }
  else if(this.nodeType == 8) {
    result = "<!--" + this.nodeValue + "-->";
    if(this.parentNode.nodeType == 9)
      result += "\n";
  }
  else if((this.nodeType == 9) && this.childCount) {
    if(this._hasXMLDecl)
      result = "<?xml version=\"1.0\"?>\n";
    for(i = 0; i < this.childCount; i++)
      result += this[i].xmlText();
  }
  return ( result );
}

//  XMLDocument

function XMLDocument(factory) {
  this._ns = new Array(); // namespace nodes pool
  this._all = new Object();
  this._elts = new Array(); // element nodes pool
  this.factory = factory;
  this._ns[0] = null; // null default namespace
  this._ns[1] = "http://www.w3.org/XML/1998/namespace"; // mandatory XML namespace
}

function XMLDocument_namespaces() {
  return ( this._ns );
}

function XMLDocument_setNodeName(node, name) {
  node.nodeName = name;
}

function XMLDocument_all(id) {
  var result = null;
  if(typeof(this._all[id]) != "undefined")
    result = this._all[id];
  return ( result );
}

function XMLDocument_createComment(text) {
  var result;
  result = new XMLComment(text);
  this._lastId++;
  result._id = this._lastId;
  result.ownerDocument = this;
  return ( result );
}

function XMLDocument_createProcessingInstruction(target, data) {
  var result;
  result = new XMLProcessingInstruction(data);
  this._lastId++;
  result._id = this._lastId;
  result.ownerDocument = this;
  this._setNodeName(result, target);
  return ( result );
}

function XMLDocument_createElement(tagName) {
  var result, b4last, last;
  result = new XMLElement();
  b4last = this._lastEI++;
  last = this._lastEI;
  result._id = last;
  this._elts[b4last] = result;
  result.ownerDocument = this;
  this._setNodeName(result, tagName);
  return ( result );
}

function XMLDocument_createTextNode(text) {
  var result;
  result = new XMLText(text);
  this._lastId++;
  result._id = this._lastId;
  result.ownerDocument = this;
  return ( result );
}

function XMLDocument_createCDATASection(text) {
  var result;
  result = new XMLCDATASection(text);
  this._lastId++;
  result._id = this._lastId;
  result.ownerDocument = this;
  return ( result );
}

function XMLDocument_getElementsByTagName(tagName, ns) {
  var result = new Array(), nelt = this._elts.length, i, elt, cnt = 0;
  for(i = 0; i < nelt; i++) {
    elt = this._elts[i];
    if(elt.named(tagName, ns))
      result[cnt++] = elt;
  }
  return ( result );
}

function XMLDocument_isLast(ofType) {
  return true;
}

function XMLContainer_getFirstChildNamed(name, ns) {
  var result, cnt, i, node;
  result = null;
  cnt = this.childCount;
  for(i = 0; i < cnt; i++) {
    node = this[i];
    if(node.nodeType == 1) {
      if(node.named(name, ns)) {
        result = node;
        break;
      }
    } else
      if(node.nodeName == name) {
        result = node;
        break;
      }
  }
  return ( result );
}

//  XMLElement

function XMLElement() {
  this._ns = new Object();
  //!!CJ bug fix #20010207.085 :
  this._ns["$xml"] = 1; // mandatory XML namespace (i.e., "http://www.w3.org/XML/1998/namespace")
  this.attributes = new Object();
}

function XMLElement_namespacePrefixes() {
  var result = new Array(), ns, i = 0;
  for(ns in this._ns)
    if(ns.length > 1)
      result[i++] = ns.substring(1, ns.length);
  return ( result );
}

function XMLElement_namespaceURI(prefix) {
  var result;
  //!!CJ bug fix #20010209.084.1 :
  if(typeof(prefix) != "undefined")
    result = this.ownerDocument._ns[this._ns["$" + prefix]];
  else
    result = this.ownerDocument._ns[this._nsi];
  return ( result );
}

function XMLElement_named(nametest, ns) {
  var name = this.nodeName, nsmark, lname;
  if(typeof(ns) == "undefined") // namespace-unaware
    return ( (name == nametest) || (nametest == "*") );
  else {
    nsmark = name.indexOf(":");
    if(nsmark > 0)
      lname = name.substring(nsmark + 1, name.length);
    else
      lname = name;
    return ( (this.namespaceURI() == ns) && ((lname == nametest) || (nametest == "*")) );
  }
}

function XMLElement_getAttribute(name, ns) {
  var result, a, nsmark, aname, pre;
  result = "";
  if(typeof(ns) == "undefined") { // namespace-unaware
    if(typeof(this.attributes["@" + name]) != "undefined")
      result = this.attributes["@" + name];
  } else
    for(a in this.attributes) {
      nsmark = a.indexOf(":");
      if(nsmark > 1) {
        aname = a.substring(nsmark + 1, a.length);
        if(aname != name)
          continue;
        pre = a.substring(1, nsmark);
        if(this._ns["$" + pre] == 1) {
          result = this.attributes["@xml:" + name];
          break;
        }
        if(this.namespaceURI(pre) == ns) {
          result = this.attributes[a];
          break;
        }
      }
    }
  return ( result );
}

function XMLElement_setAttribute(name, value) {
  this.attributes["@" + name] = value;
}

//  XMLText

function XMLText(text) {
  this.nodeValue = text;
}

//  XMLCDATASection

function XMLCDATASection(text) {
  this.nodeValue = text;
}

//  XMLProcessingInstruction

function XMLProcessingInstruction(data) {
  this.nodeValue = data;
}

//  XMLComment

function XMLComment(text) {
  this.nodeValue = text;
}

//  XMLDocumentFactory

function XMLDocumentFactory(parser) {
  this.parser = parser;
}

function XMLDocumentFactory_hasFeature(feature, version) {
  var result = false;
  if(feature.toLowerCase() == "xml")
    result = (version == "1.0");
  else if(feature.toLowerCase() == "espx-dom")
    result = (parseInt(version) <= this.parser.getVersion());
  return ( result );
}

function XMLDocumentFactory_createDocument() {
  return ( new XMLDocument(this) );
}

//  XMLParser

function XMLParser() {
  this._messages = new Array(
    "no error",
    "invalid XML declaration",
    "unsupported XML version",
    "unsupported document type declaration",
    "ill-formed document",
    "bad comment",
    "bad processing instruction",
    "invalid processing instruction target",
    "incorrect position for XML declaration",
    "'xml'-prefixed names are reserved",
    "bad end tag",
    "unexpected character(s)",
    "bad start tag",
    "duplicate attribute",
    "missing equal sign between attribute name and value",
    "bad attribute value delimiter",
    "non-legal value for 'xml:space' attribute",
    "no matching attribute value delimiter",
    "bad entity reference",
    "bad namespace URI for prefix",
    "no namespace declaration in scope",
    "bad document type declaration",
    "invalid character(s)",
    "bad document type name"
  );
  this._factory = new XMLDocumentFactory(this);
}

function XMLParser_parse(xml) {
  this._input = normalizeLineBreaks(xml);
  this._doParse();
  this._input = null; // cleanup
  return ( this.document );
}

function XMLParser_getVersion() {
  return ( __espx_version_number );
}

//  XMLParser - parse stack implementation

function XMLParser_stack_push(node) {
  this._last = node;
  this._tos++;
  this[this._tos] = node;
}

function XMLParser_stack_pop() {
  this[this._tos] = null;
  this._tos--;
  if(this._tos >= 0)
    this._last = this[this._tos];
  else
    this._last = null;
}

//  XMLParser - new parse init

function XMLParser_init() {
  this.document = null;
  this.documentTypeName = null;
  this.parseError = null;
  this._pos = 0;
  this._end = this._input.length;
  this._line = 1;
  this._column = 1;
  this._tos = -1;
  this._last = null;
  this._seenXMLDecl = false;
}

//  XMLParser - getting the job done

function XMLParser_lookForInvalidCharacters() {
  var inv = this._input.search(/\x01|\x02|\x03|\x04|\x05|\x06|\x07|\x08|\x0B|\x0C|\x0E|\x0F|\x10|\x11|\x12|\x13|\x14|\x15|\x16|\x17|\x18|\x19|\x1A|\x1B|\x1C|\x1D|\x1E|\x1F/);
  if(inv >= 0) {
    this._shiftTo(inv);
    this._raiseError(XMLPARSER_INVALID_CHAR_ERR, "", "'" + this._input.charAt(this._pos) + "'");
  }
}

function XMLParser_doParse() {
  this._init();
  this._lookForInvalidCharacters();
  if(this.parseError)
    return;
  this._parseProlog(); // <?xml ... ?>, PIs, comments, spaces
  if(!this.parseError) {
    this._parseRoot(); // the root element
    if(!this.parseError)
      if(this.document && this.document.documentElement &&
        !this.document.documentElement._closed) //!!CJ bug fix #20010101.2
        this._raiseError(XMLPARSER_ILLFORMED_DOCUMENT_ERR, "", "document element not closed");
    if(!this.parseError)
      this._parseMisc(true); // PIs, comments, spaces
  }
  // cleanup
  if(this.document)
    if(!this.parseError)
      this._pop();
    else
      while(this._tos >= 0)
        this._pop();
}

//  XMLParser - input eating

function XMLParser_shiftTo(pos) {
  var cpos, dest;
  cpos = this._pos;
  dest = cpos + pos;
  while(cpos < dest) {
    if(this._input.charCodeAt(cpos) == 10) {
      this._line++;
      this._column = 1;
    } else
      this._column++;
    cpos++;
  }
  this._pos = dest;
}

//  XMLParser - the parsing proper; utilities first

function XMLParser_prepareDoc() {
  this._push(this._factory.createDocument());
  this.document = this._last;
  this.document._hasXMLDecl = this._seenXMLDecl;
}

function isWhiteSpace(c) {
  return ( (c == '\t') || (c == '\n') || (c == '\r') || (c == " ") );
}

function XMLParser_eof() {
  return ( this._pos >= this._end );
}

function XMLParser_skipBlanks() {
  var end, pos, c;
  end = this._end;
  pos = this._pos;
  while(pos < end) {
    c = this._input.charAt(pos);
    if(isWhiteSpace(c))
      pos++;
    else
      break;
  }
  this._shiftTo(pos - this._pos);
}

function XMLParser_hasNonWhiteSpace(start, end) {
  var result, pos, c;
  result = !isWhiteSpace(this._input.charAt(start));
  pos = start;
  while(!result && (pos < end)) {
    c = this._input.charAt(pos++);
    result = !isWhiteSpace(c);
  }
  return ( result );
}

//  XMLParser - the parsing proper; XML syntax handling

function XMLParser_isXMLDecl() {
  return ( this._input.substring(this._pos, this._pos + 5) == "<?xml" );
}

function XMLParser_isComment() {
  return ( this._input.substring(this._pos, this._pos + 4) == ("<!--") );
}

function XMLParser_isPI() {
  return ( this._input.substring(this._pos, this._pos + 2) == "<?" );
}

function XMLParser_isDocTypeDecl() {
  return ( this._input.substring(this._pos, this._pos + 9) == "<!DOCTYPE" );
}

function XMLParser_isCDATASection() {
  return ( this._input.substring(this._pos, this._pos + 9) == "<![CDATA[" );
}

function XMLParser_isNamePos(cpos) {
  var result, c;
  result = !this._eof();
  if(result) {
    c = this._input.charAt(this._pos + cpos);
    result = (c == "_") || (c == ":") || ((c >= "A") && (c <= "Z")) || ((c >= "a") && (c <= "z"));
    if(cpos)
      result = result || (c == ".") || (c == "-") || ((c >= "0") && (c <= "9"));
  }
  return ( result );
}

function XMLParser_parseProlog() {
  if(this._isXMLDecl()) // <?xml ... ?>
    this._parseXMLDecl();
  if(!this.parseError) {
    this._parseMisc(false); // PIs, comments, spaces
    if(!this.parseError) {
      if(this._isDocTypeDecl()) // <!DOCTYPE ...>
        this._parseDocTypeDecl();
      if(!this.parseError)
        this._parseMisc(false); // PIs, comments, spaces again
    }
  }
}

function XMLParser_parseXMLDecl() {
  // if we find '<?xml version="1.0"?>' (at least) then we are happy
  var xmldecl_end, version_mark_end, version_mark, delim, version_end, version;
  xmldecl_end = this._input.indexOf("?>", this._pos + 5);
  if((xmldecl_end - this._pos) < 19) // 19: offset of '?>' in '<?xml version="1.0"?>'
    this._raiseError(XMLPARSER_INVALID_XMLDECL_ERR, "'<?xml version=\"1.0\" ...?>'", "(eof)");
  else {
    this._shiftTo(5);
    if(!isWhiteSpace(this._input.charAt(this._pos)))
      this._raiseError(XMLPARSER_INVALID_XMLDECL_ERR, "'<?xml version=\"1.0\" ...?>'", "'<?xml" + this._input.charAt(this._pos) + " ...?>'");
    else {
      this._skipBlanks();
      version_mark_end = 0;
      while(this._isNamePos(version_mark_end))
        version_mark_end++;
      version_mark = this._input.substring(this._pos, this._pos + version_mark_end);
      if(version_mark != "version")
        this._raiseError(XMLPARSER_INVALID_XMLDECL_ERR, "'<?xml version=\"1.0\" ...?>'", "'<?xml " + this._input.substring(this._pos, this._input.indexOf("?>", this._pos)) + "?>'");
      else {
        this._shiftTo(version_mark_end);
        this._skipBlanks();
        if(this._input.charAt(this._pos) != "=")
          this._raiseError(XMLPARSER_MISSING_EQSIGN_ERR, "", "'" + this._input.charAt(this._pos) + "'");
        else {
          this._shiftTo(1); // pass "="
          this._skipBlanks();
          delim = this._input.charAt(this._pos); // remember the delimiter
          if((delim != "\"") && (delim != "\'"))
            this._raiseError(XMLPARSER_BAD_ATTDELIM_ERR, "\" or \'", "'" + delim + "'");
          else {
            this._shiftTo(1); // pass it ...
            version_end = this._input.indexOf(delim, this._pos) - this._pos; // ... and grab its twin brother
            if((version_end < 0) || ((this._pos + version_end) > xmldecl_end))
              this._raiseError(XMLPARSER_UNMATCHED_ATTDELIM_ERR, delim, "");
            else {
              version = this._input.substring(this._pos, this._pos + version_end); // ... to get the value between them
              if(version != "1.0")
                this._raiseError(XMLPARSER_UNSUPPORTED_XMLVERSION_ERR, "'1.0'", "'" + version + "'");
              else
                this._shiftTo(xmldecl_end + 2 - this._pos); // pass "?>"
                this._seenXMLDecl = true;
            }
          }
        }
      }
    }
  }
}

function XMLParser_parseMisc(tail) {
  this._skipBlanks();
  if(!this._eof()) {
    if(tail && !this._isComment() && !this._isPI())
      this._raiseError(XMLPARSER_ILLFORMED_DOCUMENT_ERR, "comment or PI", "something else");
    if(!this.parseError)
    while(this._isComment() || this._isPI()) {
      if(this._isComment())
        this._parseComment();
      else
        this._parsePI();
      if(!this.parseError)
        this._skipBlanks();
      else
        break;
    }
  } else
    if(!this.document || !this.document.documentElement)
      this._raiseError(XMLPARSER_ILLFORMED_DOCUMENT_ERR, "document element", "(eof)");
}

function XMLParser_parseDocTypeDecl() {
  var _cpos, _end, _id, c;
  this._shiftTo(9); // pass "<!DOCTYPE"
  if(this._input.indexOf(">", this._pos) < 2) // minimal document type declaration: "<!DOCTYPE x>"
    this._raiseError(XMLPARSER_BAD_DOCTYPEDECL_ERR, ">", "");
  else {
    if(!isWhiteSpace(this._input.charAt(this._pos)))
      this._raiseError(XMLPARSER_BAD_DOCTYPEDECL_ERR, "blank", "'" + this._input.charAt(this._pos) + "'");
    else {
      this._skipBlanks();
      _cpos = this._pos;
      if(!this._isNamePos(0))
        this._raiseError(XMLPARSER_BAD_DOCTYPEDECL_ERR, "document type name", "something else");
      else {
        _end = 0;
        while(this._isNamePos(_end))
          _end++;
        _id = this._input.substring(_cpos, _cpos + _end);
        if(_id.substring(0, 3).toLowerCase() == "xml")
          this._raiseError(XMLPARSER_RESERVED_XMLNAME_ERR, "", "'" + _id + "'");
        else {
          this._shiftTo(_end);
          this.documentTypeName = _id;
          c = this._input.charAt(this._pos);
          if((c != '>') && (c != '[') && !isWhiteSpace(c))
            this._raiseError(XMLPARSER_BAD_DOCTYPEDECL_ERR, "", "'" + c + "'");
          else
            if(c != '>') {
              if(isWhiteSpace(c))
                this._skipBlanks();
              _cpos = this._pos;
              c = this._input.charAt(_cpos);
              if(c == '[')
                _end = this._input.indexOf("]>", _cpos) - _cpos + 2;
              else
                _end = this._input.indexOf(">", _cpos) - _cpos + 1;
              this._shiftTo(_end);
            } else
              this._shiftTo(1);
        }
      }
    }
  }
}

function XMLParser_parseComment() {
  var text_end, text;
  text_end = this._input.indexOf("-->", this._pos + 4) - this._pos;
  if(text_end < 0)
    this._raiseError(XMLPARSER_BAD_COMMENT_ERR, "'-->'", "(eof)");
  else
    if((this._input.indexOf("--", this._pos + 4) - this._pos) < text_end)
      this._raiseError(XMLPARSER_BAD_COMMENT_ERR, "", "'--' in comment");
    else {
      text = this._input.substring(this._pos + 4, this._pos + text_end);
      if(!this.document)
        this._prepareDoc();
      this._last._addChild(this.document.createComment(text));
      this._shiftTo(text_end + 3);
    }
}

function XMLParser_parsePI() {
  var old_pos;
  var bkc, target_end, target, data_end, data;
  old_pos = this._pos;
  data_end = this._input.indexOf("?>", this._pos + 2) - this._pos;
  if(data_end < 3)
    this._raiseError(XMLPARSER_BAD_PI_ERR, "'?>'", "(eof)");
  else {
    this._shiftTo(2); // pass "<?"
    if(!this._isNamePos(0))
      this._raiseError(XMLPARSER_UNEXPECTED_CHAR_ERR, "'<?PIName ...?>'", "'<?" + this._input.substring(this._pos, this._pos + 1) + " ...'");
    else {
      target_end = 0;
      while(this._isNamePos(target_end))
        target_end++;
      bkc = this._input.charAt(this._pos + target_end);
      if((bkc != "?") && !isWhiteSpace(bkc))
        this._raiseError(XMLPARSER_INVALID_PITARGET_ERR, "", "'<?" + this._input.substring(this._pos, this._pos + target_end + 1) + " ...'");
      else {
        target = this._input.substring(this._pos, this._pos + target_end);
        if(target.toLowerCase() == "xml")
          this._raiseError(XMLPARSER_INCORRECT_XMLDECLPOS_ERR, "", "");
        else {
          this._shiftTo(target_end);
          this._skipBlanks();
          data = this._input.substring(this._pos, old_pos + data_end);
          if(!this.document)
            this._prepareDoc();
          this._last._addChild(this.document.createProcessingInstruction(target, data));
          this._shiftTo(old_pos + data_end - this._pos + 2);
        }
      }
    }
  }
}

function endTagName(str) {
  var lastc;
  lastc = str.length - 1;
  while((lastc > 0) && isWhiteSpace(str.charAt(lastc)))
    lastc--;
  return ( str.substring(0, lastc + 1) );
}

function XMLParser_parseRoot() {
  var etagc, str, markup;
  if(!this.document)
    this._prepareDoc();
  this.document.documentElement = this._parseElement();
  if(!this.parseError)
    if(this.documentTypeName && (this.document.documentElement.nodeName != this.documentTypeName))
      this._raiseError(XMLPARSER_BAD_DOCTYPENAME_ERR, "'" + this.documentTypeName + "'", "'" + this.document.documentElement.nodeName + "'");
  if(!this.parseError) {
    while((this._tos > 0) && !this._eof()) {
      if((this._last.getAttribute("xml:space") == "default") && !this.preserveWhiteSpace) {
        markup = this._input.indexOf("<", this._pos);
        if((markup >= 0) && !this._hasNonWhiteSpace(this._pos, markup)) {
          this._skipBlanks();
          continue;
        }
      }
      if(this._input.substring(this._pos, this._pos + 2) == "</") {
        etagc = this._input.indexOf(">", this._pos + 2);
        if(etagc < (this._pos + 3)) {
          this._raiseError(XMLPARSER_BAD_ETAG_ERR, "'</TagName>'", "(eof)");
          break;
        }
        str = this._input.substring(this._pos + 2, etagc);
        if(endTagName(str) != this._last.nodeName) {
          this._raiseError(XMLPARSER_BAD_ETAG_ERR, "'</" + this._last.nodeName + ">'", "'</" + str + ">'");
          break;
        } else {
          this._last._closed = true;
          this._pop();
          this._shiftTo(etagc - this._pos + 1);
        }
      } else if(!this._last._opened && (this._input.substring(this._pos, this._pos + 1) == "/")) { //!!CJ bug fix #20010101.1 (start)
        etagc = this._input.substring(this._pos + 1, this._pos + 2);
        if(etagc != ">") { //!!CJ bug fix #20010101.1 (end)
          if(etagc != "")
            this._raiseError(XMLPARSER_BAD_STAG_ERR, "'>'", "'" + etagc + "'");
          else
            this._raiseError(XMLPARSER_BAD_STAG_ERR, "'>'", "(eof)");
        } else {
          this._last._closed = true;
          this._pop();
          this._shiftTo(2);
        }
      } else if(this._isComment())
          this._parseComment();
        else if(this._isPI())
          this._parsePI();
        else if(this._isCDATASection())
          this._parseCDATASection();
        else if(this._input.charAt(this._pos) == "<") // here's the evidence ...
          this._parseElement(); // ... of our "no direct recursion" approach
        else
          this._parseText();
      if(this.parseError)
        break;
    }
  }
}

function XMLParser_parseElement() {
  var result, name_end, name, lastc, a_pos;
  result = null;
  if(this._input.indexOf(">", this._pos + 1) < 0)
    this._raiseError(XMLPARSER_BAD_STAG_ERR, "'>'", "(eof)");
  else {
    this._shiftTo(1); // pass "<"
    if(!this._isNamePos(0))
      this._raiseError(XMLPARSER_UNEXPECTED_CHAR_ERR, "'<TagName ...>'", "'<" + this._input.substring(this._pos, this._pos + 1) + " ...'");
    else {
      name_end = 0;
      while(this._isNamePos(name_end))
        name_end++;
      name = this._input.substring(this._pos, this._pos + name_end);
      if((name.substring(0, 3).toLowerCase() == "xml") && (name.indexOf(":") >= 3)) //!!CJ bug fix #20010114.1
        this._raiseError(XMLPARSER_RESERVED_XMLNAME_ERR, "", "'<" + name + " ...'");
      else {
        result = this.document.createElement(name);
        this._last._addChild(result);
        this._push(result);
        if(this._last.parentNode.nodeType == 9)
          this._last.setAttribute("xml:space", "default"); // if we are the root element set xml:space to "default" by ... default
        else
          this._last.setAttribute("xml:space", this._last.parentNode.getAttribute("xml:space")); // else inherit xml:space's value from our parent
        if(this._last.parentNode.nodeType == 9)
          this._last.setAttribute("xml:lang", this.xmlLang); // if we are the root element set xml:lang to the parser's default
        else
          this._last.setAttribute("xml:lang", this._last.parentNode.getAttribute("xml:lang")); // else inherit xml:lang's value from our parent
        if(this._last.parentNode.nodeType == 9)
          this._last.setAttribute("xml:base", this.xmlBase); // if we are the root element set xml:base to the parser's default
        else
          this._last.setAttribute("xml:base", this._last.parentNode.getAttribute("xml:base")); // else inherit xml:base's value from our parent
        this._shiftTo(name_end);
        this._skipBlanks();
        a_pos = this._pos;
        lastc = this._input.charAt(a_pos);
        if((lastc == ">") || (lastc == "/")) {
          if(lastc == ">") {
            this._shiftTo(1);
            this._last._opened = true;
          }
          if(this.namespaceAware)
            this._nsScoping(this._last);
        } else if(this._isNamePos(0)) {
          while(this._isNamePos(0)) { // time to eat attributes
            this._parseAttr();
            if(this.parseError)
              break;
          }
          if(!this.parseError && !this._eof() && this.namespaceAware) {
            this._nsHandling(this._last);
            if(!this.parseError) {
              this._nsScoping(this._last);
              this._nsValidation(this._last);
            }
          }
          if(!this.parseError && !this._eof()) {
            lastc = this._input.charAt(this._pos);
            if(lastc == ">") {
              this._shiftTo(1);
              this._last._opened = true;
            } else if(lastc != "/")
              this._raiseError(XMLPARSER_UNEXPECTED_CHAR_ERR, "'>' or '/>'", "'" + lastc + "'");
          }
        } else
          this._raiseError(XMLPARSER_UNEXPECTED_CHAR_ERR, "'>' or '/>'", "'" + lastc + "'");
      }
    }
  }
  return ( result );
}

function XMLParser_parseAttr() {
  var name_end, name, delim, value_end, value;
  name_end = 0;
  while(this._isNamePos(name_end))
    name_end++;
  name = this._input.substring(this._pos, this._pos + name_end);
  if((this._last._xmlspace && (name == "xml:space")) || //!!CJ bug fix #20010101.3 (start)
    (this._last._xmllang && (name == "xml:lang")) || //!!CJ bug fix #20010101.3 (end)
    (this._last._xmlbase && (name == "xml:base")) ||
    ((name != "xml:space") && (name != "xml:lang") && (name != "xml:base") &&
    (this._last._attlist.indexOf("@" + name + "$") >= 0))) //!!CJ bug fix #20010112.1 (start) + bug fix #20010129.088 (start)
    this._raiseError(XMLPARSER_DUPLICATE_ATTRIBUTE_ERR, "", "'" + name + "'");
  else {
    if(name.substring(0, 9).toLowerCase() == "xmlns:xml") //!!CJ bug fix #20010114.1
      this._raiseError(XMLPARSER_RESERVED_XMLNAME_ERR, "", "'" + name + "'");
    else {
      this._shiftTo(name_end);
      this._skipBlanks();
      if(this._input.charAt(this._pos) != "=")
        this._raiseError(XMLPARSER_MISSING_EQSIGN_ERR, "", "'" + this._input.charAt(this._pos) + "'");
      else {
        this._shiftTo(1); // pass "="
        this._skipBlanks();
        delim = this._input.charAt(this._pos); // remember the delimiter
        if((delim != "\"") && (delim != "\'"))
          this._raiseError(XMLPARSER_BAD_ATTDELIM_ERR, "\" or \'", "'" + delim + "'");
        else {
          this._shiftTo(1); // pass it ...
          value_end = this._input.indexOf(delim, this._pos) - this._pos; // ... and grab its twin brother
          if(value_end < 0)
            this._raiseError(XMLPARSER_UNMATCHED_ATTDELIM_ERR, "'" + delim + "'", "");
          else {
            value = this._input.substring(this._pos, this._pos + value_end); // ... to get the value between them
            if(value.indexOf("<") >= 0)
              this._raiseError(XMLPARSER_UNEXPECTED_CHAR_ERR, "", "'<' in attribute value");
            else {
              this._shiftTo(value_end + 1);
              value = expandReferences(this.document, value);
              if(value.charCodeAt(0) == 0xEEEE)
                this._raiseError(XMLPARSER_BAD_ENTITYREF_ERR, "", "'" + value.substring(1, value.length) + " ...'");
              else {
                if((name == "xml:space") && (value != "default") && (value != "preserve"))
                  this._raiseError(XMLPARSER_ILLEGAL_XMLSPACEATTR_ERR, "'default' or 'preserve'", "'" + value + "'");
                else {
                  // just let the element at top of stack create the attribute for us
                  this._last.setAttribute(name, value);
                  this._last._xmlspace = this._last._xmlspace || (name == "xml:space"); // xml:space now specified
                  this._last._xmllang = this._last._xmllang || (name == "xml:lang"); // xml:lang now specified
                  this._last._xmlbase = this._last._xmlbase || (name == "xml:base"); // xml:base now specified
                  if((name != "xml:space") && (name != "xml:lang") && (name != "xml:base")) //!!CJ bug fix #20010112.1 (end)
                    this._last._attlist += "@" + name + "$"; //!!CJ bug fix #20010129.088.1 (end)
                  if(name == "id")
                    this.document._all[value] = this._last;
                  // finally, shift to the next attribute, if any
                  this._skipBlanks();
                }
              }
            }
          }
        }
      }
    }
  }
}

function XMLParser_nsHandling(elt) {
  var a, pre, ns;
  for(a in elt.attributes)
    if(a.substring(0, 6) == "@xmlns") {
      if(this.parseError)
        break;
      if(a.length == 6)
        pre = "";
      else
        if(a.indexOf(":") > 0)
          pre = a.substring(a.indexOf(":") + 1, a.length);
        else
          this._raiseError(XMLPARSER_RESERVED_XMLNAME_ERR, "", "'" + a.substring(1, a.length) + "'");
      if(this.parseError)
        break;
      ns = elt.attributes[a];
      if(ns == "")
        if(pre == "")
          elt._ns["$"] = 0; // default namespace is now null
        else
          this._raiseError(XMLPARSER_BAD_NSURI_ERR, "", "xmlns:" + pre + "=''");
      else
        this._nsDeclaration(elt, pre, ns);
    }
}

function XMLParser_nsDeclaration(elt, pre, ns) {
  var allns = this.document._ns, n, i = 0, found = 0;
  n = allns.length;
  while((++i < n) && !found)
    found = (allns[i] == ns) ? i : 0;
  if(!found) {
    allns[i] = ns;
    found = i;
  }
  elt._ns["$" + pre] = found;
}

function XMLParser_nsScoping(elt) {
  var pre = "", nsmark = elt.nodeName.indexOf(":"), nsi;
  if(nsmark > 0)
    pre = elt.nodeName.substring(0, nsmark);
  nsi = elt._ns["$" + pre];
  if(typeof(nsi) == "undefined")
    this._raiseError(XMLPARSER_NO_NSINSCOPE_ERR, "", "namespace prefix '" + pre + "'");
  else
    elt._nsi = nsi;
}

function XMLParser_nsValidation(elt) {
  var a, nam, c, pre, nsi, lnam, qna, qnas = "";
  for(a in elt.attributes) {
    nam = a.substring(1, a.length);
    c = nam.indexOf(":");
    if(c > 0) {
      pre = nam.substring(0, c);
      if(pre.substring(0, 5) == "xmlns")
        continue;
      nsi = elt._ns["$" + pre];
      if(typeof(nsi) == "undefined")
        this._raiseError(XMLPARSER_NO_NSINSCOPE_ERR, "", "namespace prefix '" + pre + "'");
      else {
        lnam = nam.substring(c + 1, nam.length);
        qna = "@" + nsi + lnam + "$";
        if(nsi == 1) {
          if(pre == "xml")
            continue;
          if((lnam != "space") && (lnam != "lang") && (lnam != "base")) {
            this._raiseError(XMLPARSER_RESERVED_XMLNAME_ERR, "", "'xml:" + lnam + "'");
          } else if(lnam == "space") {
            if(!elt._xmlspace) {
              elt.attributes["@xml:space"] = elt.attributes[a];
              elt._xmlspace = true;
            } else
              this._raiseError(XMLPARSER_DUPLICATE_ATTRIBUTE_ERR, "", "'xml:space'");
          } else if(lnam == "lang") {
            if(!elt._xmllang) {
              elt.attributes["@xml:lang"] = elt.attributes[a];
              elt._xmllang = true;
            } else
              this._raiseError(XMLPARSER_DUPLICATE_ATTRIBUTE_ERR, "", "'xml:lang'");
          } else if(lnam == "base") {
            if(!elt._xmlbase) {
              elt.attributes["@xml:base"] = elt.attributes[a];
              elt._xmlbase = true;
            } else
              this._raiseError(XMLPARSER_DUPLICATE_ATTRIBUTE_ERR, "", "'xml:base'");
          }
        }
        else
        if(qnas.indexOf(qna) >= 0)
          this._raiseError(XMLPARSER_DUPLICATE_ATTRIBUTE_ERR, "", "'" + lnam + "'");
        else
          qnas += qna;
      }
    }
    if(this.parseError)
      break;
  }
}

function XMLParser_parseText() {
  var text_end, cds_end, text, done, last, last_sibling;
  text_end = this._input.indexOf("<", this._pos + 1) - this._pos;
  cds_end = this._input.indexOf("]]>", this._pos) - this._pos;
  if(text_end < 0)
    this._raiseError(XMLPARSER_UNEXPECTED_CHAR_ERR, "'</" + this._last.nodeName + ">'", "(eof)");
  else
    if((cds_end >= 0) && (cds_end < text_end))
      this._raiseError(XMLPARSER_ILLFORMED_DOCUMENT_ERR, "", "']]>'");
    else {
      text = this._input.substring(this._pos, this._pos + text_end);
      text = expandReferences(this.document, text);
      if(text.charCodeAt(0) == 0xEEEE)
        this._raiseError(XMLPARSER_BAD_ENTITYREF_ERR, "", "'" + text.substring(1, text.length) + " ...'");
      else {
        done = false;
        last = this._last;
        if(last.childCount) {
          last_sibling = last[last.childCount - 1];
          if((last_sibling.nodeType == 3) || (last_sibling.nodeType == 4)) {
            last_sibling.nodeValue += text;
            done = true;
          }
        }
        if(!done)
          last._addChild(this.document.createTextNode(text));
        this._shiftTo(text_end);
      }
    }
}

function XMLParser_parseCDATASection() {
  var cdata_end, cdata, done, last, last_sibling;
  cdata_end = this._input.indexOf("]]>", this._pos + 9) - this._pos;
  if(cdata_end < 0)
    this._raiseError(XMLPARSER_UNEXPECTED_CHAR_ERR, "']]>'", "(eof)");
  else if(this._input.indexOf("<", this._pos + cdata_end + 3) < 0)
    this._raiseError(XMLPARSER_UNEXPECTED_CHAR_ERR, "'</" + this._last.nodeName + ">'", "(eof)");
  else {
    cdata = this._input.substring(this._pos + 9, this._pos + cdata_end);
    done = false;
    last = this._last;
    if(last.childCount) {
      last_sibling = last[last.childCount - 1];
      if((last_sibling.nodeType == 3) || (last_sibling.nodeType == 4)) {
        last_sibling.nodeValue += cdata;
        done = true;
      }
    }
    if(!done)
      last._addChild(this.document.createCDATASection(cdata));
    this._shiftTo(cdata_end + 3);
  }
}

//  XMLParser - error handling

function XMLParser_raiseError(code, expected, found) {
  this.parseError = new XMLParseError(this, code, expected, found);
}

//  XMLParseError

function XMLParseError(ps, ec, xp, fd) {
  var msg;
  this.parser = ps;
  this.code = ec;
  this.line = this.parser._line;
  this.column = this.parser._column;
  msg = "error in line " + this.line.toString() + ", column " + this.column.toString() + "\t" + this.parser._messages[ec];
  if(xp != "")
    msg += "; expected: " + xp;
  if(fd != "")
    msg += "; found: " + fd;
  this.message = msg;
}

//  Line breaks normalization, entity reference expansion

function normalizeLineBreaks(xml) {
  // simple but efficient enough if done once for all (here in XMLParser.parse())
  var result, norm;
  result = xml;
  norm = result.split("\r\n");
  result = norm.join("\n");
  norm = result.split("\r");
  result = norm.join("\n");
  return ( result );
}

function expandReferences(xdoc, xml) {
  var result, str, iref, lhs, ref, rhs, refend;
  var eerr = false;
  result = "";
  str = xml;
  iref = str.indexOf("&");
  while((iref >= 0) && !eerr) {
    lhs = str.substring(0, iref);
    rhs = str.substring(iref, str.length);
    refend = rhs.indexOf(";");
    eerr = (refend < 0) || ((rhs.indexOf("&", 1) > 0) && (refend > rhs.indexOf("&", 1)));
    if(!eerr) { //!!CJ bug fix #20010114.2
      ref = rhs.substring(0, refend + 1);
      rhs = rhs.substring(refend + 1, rhs.length);
      if(ref.charAt(1) == "#")
        result += lhs + expandCharRef(ref);
      else
        result += lhs + expandEntityRef(xdoc, ref);
      str = rhs;
      iref = str.indexOf("&");
    } else {
      result = str.substring(iref + 1, iref + 51);
      break;
    }
  }
  if(!eerr)
    result += str;
  else
    result = "\uEEEE&" + result;
  return ( result );
}

function expandCharRef(cref) {
  var str, result;
  str = cref.substring(cref.indexOf("#") + 1, cref.indexOf(";"));
  if(str.charAt(0) == "x") // make parseInt happy with "0xhhhh" instead of "xhhhh"
    str = "0" + str;
  else { // strip leading zeroes if no "x" aside, otherwise parseInt will think this is octal
    while(str.charAt(0) == "0")
      str = str.substring(1, str.length);
  }
  result = String.fromCharCode(str); //!!CJ bug fix #20010107.2
  return ( result );
}

function expandEntityRef(xdoc, eref) {
  var result, enam, s, n, e;
  if(eref == "&amp;")
    result = "&";
  else if(eref == "&apos;")
    result = "\'";
  else if(eref == "&gt;")
    result = ">";
  else if(eref == "&lt;")
    result = "<";
  else if(eref == "&quot;")
    result = "\"";
  else {
    enam = eref.substring(1, eref.length - 1);
    s = xdoc._ents.indexOf(enam + "<");
    if(s >= 0) {
      n = enam.length;
      e = xdoc._ents.indexOf("<", s + n + 1);
      result = xdoc._ents.substring(s + n + 1, e);
    } else if(typeof(__entities[enam]) != "undefined")
      result = String.fromCharCode(__entities[enam]);
    else // well, let's show what was his/her mind, since we don't support (yet) the doctype stuff
      result = eref;
  }
  return ( result );
}
