diff options
Diffstat (limited to 'includes/js/dojox/xml/DomParser.js')
-rw-r--r-- | includes/js/dojox/xml/DomParser.js | 379 |
1 files changed, 379 insertions, 0 deletions
diff --git a/includes/js/dojox/xml/DomParser.js b/includes/js/dojox/xml/DomParser.js new file mode 100644 index 0000000..f61e653 --- /dev/null +++ b/includes/js/dojox/xml/DomParser.js @@ -0,0 +1,379 @@ +if(!dojo._hasResource["dojox.xml.DomParser"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code. +dojo._hasResource["dojox.xml.DomParser"] = true; +dojo.provide("dojox.xml.DomParser"); + +dojox.xml.DomParser=new (function(){ + /********************************************************** + * The DomParser is a close-to (but not entirely) + * conforming XML parser based on regular + * expressions. It will take any XML fragment + * and return a lightweight JS structure that is + * similar to (but not exactly) the DOM specification. + * + * Getter and setter methods are NOT available; the goal + * was to keep the resulting object model entirely JS-like. + * + * All node types but document fragments are supported; + * all nodes support getElementsByTagName and + * getElementsByTagNameNS (with short names byName and + * byNameNS). The document node supports getElementById + * (byId), and all nodes support a supplimental + * childrenByName/childrenByNameNS method as well. + * + * The object model is intended to be a READONLY format; + * mutation events are NOT supported, and though you + * can change properties on a node-by-node basis, certain + * operations are not supported (such as changing the ID + * of an element). + **********************************************************/ + + // internal use only. + var nodeTypes={ ELEMENT:1, ATTRIBUTE:2, TEXT:3, CDATA_SECTION:4, PROCESSING_INSTRUCTION:7, COMMENT:8, DOCUMENT:9 }; + + // compile the regular expressions once. + var reTags=/<([^>\/\s+]*)([^>]*)>([^<]*)/g; + var reAttr=/([^=]*)="([^"]*)"/g; + var reEntity=/<!ENTITY\s+([^"]*)\s+"([^"]*)">/g; + var reCData=/<!\[CDATA\[([\u0001-\uFFFF]*?)\]\]>/g; + var reComments=/<!--([\u0001-\uFFFF]*?)-->/g; + var trim=/^\s+|\s+$/g; + var normalize=/\s+/g; + var egt=/\>/g; + var elt=/\</g; + var equot=/\"/g; + var eapos=/\'/g; + var eamp=/\&/g; + var dNs="_def_"; + + // create a root node. + function _doc(){ + return new (function(){ + var all={}; + this.nodeType=nodeTypes.DOCUMENT; + this.nodeName="#document"; + this.namespaces={}; + this._nsPaths={}; + this.childNodes=[]; + this.documentElement=null; + + // any element with an ID attribute will be added to the internal hashtable. + this._add=function(obj){ + if(typeof(obj.id)!="undefined"){ all[obj.id]=obj; } + }; + this._remove=function(id){ + if(all[id]){ delete all[id]; } + }; + + this.byId=this.getElementById=function(id){ return keys[id]; }; + this.byName=this.getElementsByTagName=byName; + this.byNameNS=this.getElementsByTagNameNS=byNameNS; + this.childrenByName=childrenByName; + })(); + } + + // functions attached to element nodes + function byName(name){ + // return all descendants with name. Fully qualified (i.e. svg:svg) + function __(node, name, arr){ + dojo.forEach(node.childNodes, function(c){ + if(c.nodeType==nodeTypes.ELEMENT){ + if(name=="*"){ arr.push(c); } + else if(c.nodeName==name){ arr.push(c); } + __(c, name, arr); + } + }); + } + var a=[]; + __(this, name, a); + return a; + } + function byNameNS(name, ns){ + // return all descendants with name by namespace. If no namespace passed, the default is used. + function __(node, name, ns, arr){ + dojo.forEach(node.childNodes, function(c){ + if(c.nodeType==nodeTypes.ELEMENT){ + if(name=="*"&&c.ownerDocument._nsPaths[ns]==c.namespace){ arr.push(c); } + else if(c.localName==name&&c.ownerDocument._nsPaths[ns]==c.namespace){ arr.push(c); } + __(c, name, ns, arr); + } + }); + } + if(!ns){ ns=dNs; } + var a=[]; + __(this, name, ns, a); + return a; + } + // Only child nodes with name. + function childrenByName(name){ + var a=[]; + dojo.forEach(this.childNodes, function(c){ + if(c.nodeType==nodeTypes.ELEMENT){ + if(name=="*"){ a.push(c); } + else if(c.nodeName==name){ a.push(c); } + } + }); + return a; + } + + function _createTextNode(v){ + return { + nodeType:nodeTypes.TEXT, + nodeName:"#text", + nodeValue:v.replace(normalize," ").replace(egt,">").replace(elt,"<").replace(eapos,"'").replace(equot,'"').replace(eamp,"&") + }; + } + + // attribute functions + function getAttr(name){ + for(var i=0; i<this.attributes.length; i++){ + if(this.attributes[i].nodeName==name){ + return this.attributes[i].nodeValue; + } + } + return null; + } + function getAttrNS(name, ns){ + for(var i=0; i<this.attributes.length; i++){ + if(this.ownerDocument._nsPaths[ns]==this.attributes[i].namespace + &&this.attributes[i].localName==name + ){ + return this.attributes[i].nodeValue; + } + } + return null; + } + // note that you can only swap IDs using setAttribute, NOT with setAttributeNS. + function setAttr(name, val){ + var old=null; + for(var i=0; i<this.attributes.length; i++){ + if(this.attributes[i].nodeName==name){ + old=this.attributes[i].nodeValue; + this.attributes[i].nodeValue=val; + break; + } + } + if(name=="id"){ + if(old!=null){ this.ownerDocument._remove(old); } + this.ownerDocument._add(this); + } + } + function setAttrNS(name, val, ns){ + for(var i=0; i<this.attributes.length; i++){ + if(this.ownerDocument._nsPaths[ns]==this.attributes[i].namespace + &&this.attributes[i].localName==name + ){ + this.attributes[i].nodeValue=val; + return; + } + } + } + + // navigation + function prev(){ + var p=this.parentNode; + if(p){ + for(var i=0;i<p.childNodes.length;i++){ + if(p.childNodes[i]==this&&i>0){ + return p.childNodes[i-1]; + } + } + } + return null; + } + function next(){ + var p=this.parentNode; + if(p){ + for(var i=0;i<p.childNodes.length;i++){ + if(p.childNodes[i]==this&&(i+1)<p.childNodes.length){ + return p.childNodes[i+1]; + } + } + } + return null; + } + + // the main method. + this.parse=function(/* String */str){ + var root=_doc(); + if(str==null){ return root; } + if(str.length==0){ return root; } + + // preprocess custom entities + if(str.indexOf("<!ENTITY")>0){ + var entity, eRe=[]; + if(reEntity.test(str)){ + reEntity.lastIndex=0; + // match entities + while((entity=reEntity.exec(str))!=null){ + eRe.push({ + entity:"&"+entity[1].replace(trim,"")+";", + expression:entity[2] + }); + } + // replace instances in the document. + for(var i=0; i<eRe.length; i++){ + str=str.replace(new RegExp(eRe[i].entity, "g"), eRe[i].expression); + } + } + } + + // pre-parse for CData, and tokenize. + var cdSections=[], cdata; + while((cdata=reCData.exec(str))!=null){ cdSections.push(cdata[1]); } + for(var i=0; i<cdSections.length; i++){ str=str.replace(cdSections[i], i); } + + // pre-parse for comments, and tokenize. + var comments=[], comment; + while((comment=reComments.exec(str))!=null){ comments.push(comment[1]); } + for(i=0; i<comments.length; i++){ str=str.replace(comments[i], i); } + + // parse the document + var res, obj=root; + while((res=reTags.exec(str))!=null){ + // closing tags. + if(res[2].charAt(0)=="/"){ + if(obj.parentNode){ + obj=obj.parentNode; + } + var text=res[3]; + if(text.length>0) + obj.appendChild(_createTextNode(text)); + }else + + // open tags. + if(res[1].length>0){ + // figure out the type of node. + if(res[1].charAt(0)=="?"){ + // processing instruction + var name=res[1].substr(1); + var target=res[2].substr(0,res[2].length-2); + obj.childNodes.push({ + nodeType:nodeTypes.PROCESSING_INSTRUCTION, + nodeName:name, + nodeValue:target + }); + } + else if(res[1].charAt(0)=="!"){ + // CDATA; skip over any declaration elements. + if(res[1].indexOf("![CDATA[")==0){ + var val=parseInt(res[1].replace("![CDATA[","").replace("]]","")); + obj.childNodes.push({ + nodeType:nodeTypes.CDATA_SECTION, + nodeName:"#cdata-section", + nodeValue:cdSections[val] + }); + } + // Comments. + else if(res[1].substr(0,3)=="!--"){ + var val=parseInt(res[1].replace("!--","").replace("--","")); + obj.childNodes.push({ + nodeType:nodeTypes.COMMENT, + nodeName:"#comment", + nodeValue:comments[val] + }); + } + } + else { + // Elements (with attribute and text) + var name=res[1].replace(trim,""); + var o={ + nodeType:nodeTypes.ELEMENT, + nodeName:name, + localName:name, + namespace:dNs, + ownerDocument:root, + attributes:[], + parentNode:null, + childNodes:[] + }; + + // check to see if it's namespaced. + if(name.indexOf(":")>-1){ + var t=name.split(":"); + o.namespace=t[0]; + o.localName=t[1]; + } + + // set the function references. + o.byName=o.getElementsByTagName=byName; + o.byNameNS=o.getElementsByTagNameNS=byNameNS; + o.childrenByName=childrenByName; + o.getAttribute=getAttr; + o.getAttributeNS=getAttrNS; + o.setAttribute=setAttr; + o.setAttributeNS=setAttrNS; + o.previous=o.previousSibling=prev; + o.next=o.nextSibling=next; + + // parse the attribute string. + var attr; + while((attr=reAttr.exec(res[2]))!=null){ + if(attr.length>0){ + var name=attr[1].replace(trim,""); + var val=attr[2].replace(normalize," ") + .replace(egt,">") + .replace(elt,"<") + .replace(eapos,"'") + .replace(equot,'"') + .replace(eamp,"&"); + if(name.indexOf("xmlns")==0){ + if(name.indexOf(":")>0){ + var ns=name.split(":"); + root.namespaces[ns[1]]=val; + root._nsPaths[val]=ns[1]; + } else { + root.namespaces[dNs]=val; + root._nsPaths[val]=dNs; + } + } else { + var ln=name; + var ns=dNs; + if(name.indexOf(":")>0){ + var t=name.split(":"); + ln=t[1]; + ns=t[0]; + } + o.attributes.push({ + nodeType:nodeTypes.ATTRIBUTE, + nodeName:name, + localName:ln, + namespace:ns, + nodeValue:val + }); + + // only add id as a property. + if(ln=="id"){ o.id=val; } + } + } + } + root._add(o); + + if(obj){ + obj.childNodes.push(o); + o.parentNode=obj; + // if it's not a self-closing node. + if(res[2].charAt(res[2].length-1)!="/"){ + obj=o; + } + } + var text=res[3]; + if(text.length>0){ + obj.childNodes.push(_createTextNode(text)); + } + } + } + } + + // set the document element + for(var i=0; i<root.childNodes.length; i++){ + var e=root.childNodes[i]; + if(e.nodeType==nodeTypes.ELEMENT){ + root.documentElement=e; + break; + } + } + return root; + }; +})(); + +} |