/* 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 = /\ 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 += ""; } else result += "/>"; if(this.parentNode.nodeType == 9) result += "\n"; } else if(this.nodeType == 3) result = this.nodeValue.replace(re_amp, "&").replace(re_lt, "<"); else if(this.nodeType == 4) result = ""; else if(this.nodeType == 7) { result = ""; if(this.parentNode.nodeType == 9) result += "\n"; } else if(this.nodeType == 8) { result = ""; if(this.parentNode.nodeType == 9) result += "\n"; } else if((this.nodeType == 9) && this.childCount) { if(this._hasXMLDecl) result = "\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(); // , 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) == "= "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()) // this._parseXMLDecl(); if(!this.parseError) { this._parseMisc(false); // PIs, comments, spaces if(!this.parseError) { if(this._isDocTypeDecl()) // this._parseDocTypeDecl(); if(!this.parseError) this._parseMisc(false); // PIs, comments, spaces again } } } function XMLParser_parseXMLDecl() { // if we find '' (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 '' this._raiseError(XMLPARSER_INVALID_XMLDECL_ERR, "''", "(eof)"); else { this._shiftTo(5); if(!isWhiteSpace(this._input.charAt(this._pos))) this._raiseError(XMLPARSER_INVALID_XMLDECL_ERR, "''", "''"); 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, "''", "'", 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 "", this._pos) < 2) // minimal document type declaration: "" 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 "'", "' 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) == "", this._pos + 2); if(etagc < (this._pos + 3)) { this._raiseError(XMLPARSER_BAD_ETAG_ERR, "''", "(eof)"); break; } str = this._input.substring(this._pos + 2, etagc); if(endTagName(str) != this._last.nodeName) { this._raiseError(XMLPARSER_BAD_ETAG_ERR, "''", "''"); 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, "''", "'<" + 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, "''", "(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, "''", "(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 == "&") result = "&"; else if(eref == "'") result = "\'"; else if(eref == ">") result = ">"; else if(eref == "<") result = "<"; else if(eref == """) 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 ); }