Subversion Repositories Applications.papyrus

Rev

Blame | Last modification | View Log | RSS feed

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=/\&gt;/g;
        var elt=/\&lt;/g;
        var equot=/\&quot;/g;
        var eapos=/\&apos;/g;
        var eamp=/\&amp;/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;
        }

        //      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;
                                }
                                continue;
                        }

                        //      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);

                                        var text=res[3].replace(trim,"");
                                        if(text.length>0)
                                                o.childNodes.push({ 
                                                        nodeType:nodeTypes.TEXT, 
                                                        nodeName:"#text", 
                                                        nodeValue:text.replace(normalize," ").replace(egt,">").replace(elt,"<").replace(eapos,"'").replace(equot,'"').replace(eamp,"&") 
                                                });

                                        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;
                                                }
                                        }
                                }
                        }
                }

                //      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;
        };
})();

}