"Fossies" - the Fresh Open Source Software Archive

Member "Atom/resources/app/apm/node_modules/xmldom/sax.js" (11 Apr 2017, 19321 Bytes) of package /windows/misc/atom-windows.zip:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) Javascript source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file.

    1 //[4]       NameStartChar      ::=      ":" | [A-Z] | "_" | [a-z] | [#xC0-#xD6] | [#xD8-#xF6] | [#xF8-#x2FF] | [#x370-#x37D] | [#x37F-#x1FFF] | [#x200C-#x200D] | [#x2070-#x218F] | [#x2C00-#x2FEF] | [#x3001-#xD7FF] | [#xF900-#xFDCF] | [#xFDF0-#xFFFD] | [#x10000-#xEFFFF]
    2 //[4a]      NameChar       ::=      NameStartChar | "-" | "." | [0-9] | #xB7 | [#x0300-#x036F] | [#x203F-#x2040]
    3 //[5]       Name       ::=      NameStartChar (NameChar)*
    4 var nameStartChar = /[A-Z_a-z\xC0-\xD6\xD8-\xF6\u00F8-\u02FF\u0370-\u037D\u037F-\u1FFF\u200C-\u200D\u2070-\u218F\u2C00-\u2FEF\u3001-\uD7FF\uF900-\uFDCF\uFDF0-\uFFFD]///\u10000-\uEFFFF
    5 var nameChar = new RegExp("[\\-\\.0-9"+nameStartChar.source.slice(1,-1)+"\\u00B7\\u0300-\\u036F\\u203F-\\u2040]");
    6 var tagNamePattern = new RegExp('^'+nameStartChar.source+nameChar.source+'*(?:\:'+nameStartChar.source+nameChar.source+'*)?$');
    7 //var tagNamePattern = /^[a-zA-Z_][\w\-\.]*(?:\:[a-zA-Z_][\w\-\.]*)?$/
    8 //var handlers = 'resolveEntity,getExternalSubset,characters,endDocument,endElement,endPrefixMapping,ignorableWhitespace,processingInstruction,setDocumentLocator,skippedEntity,startDocument,startElement,startPrefixMapping,notationDecl,unparsedEntityDecl,error,fatalError,warning,attributeDecl,elementDecl,externalEntityDecl,internalEntityDecl,comment,endCDATA,endDTD,endEntity,startCDATA,startDTD,startEntity'.split(',')
    9 
   10 //S_TAG,    S_ATTR, S_EQ,   S_ATTR_NOQUOT_VALUE
   11 //S_ATTR_SPACE, S_ATTR_END, S_TAG_SPACE, S_TAG_CLOSE
   12 var S_TAG = 0;//tag name offerring
   13 var S_ATTR = 1;//attr name offerring 
   14 var S_ATTR_SPACE=2;//attr name end and space offer
   15 var S_EQ = 3;//=space?
   16 var S_ATTR_NOQUOT_VALUE = 4;//attr value(no quot value only)
   17 var S_ATTR_END = 5;//attr value end and no space(quot end)
   18 var S_TAG_SPACE = 6;//(attr value end || tag end ) && (space offer)
   19 var S_TAG_CLOSE = 7;//closed el<el />
   20 
   21 function XMLReader(){
   22     
   23 }
   24 
   25 XMLReader.prototype = {
   26     parse:function(source,defaultNSMap,entityMap){
   27         var domBuilder = this.domBuilder;
   28         domBuilder.startDocument();
   29         _copy(defaultNSMap ,defaultNSMap = {})
   30         parse(source,defaultNSMap,entityMap,
   31                 domBuilder,this.errorHandler);
   32         domBuilder.endDocument();
   33     }
   34 }
   35 function parse(source,defaultNSMapCopy,entityMap,domBuilder,errorHandler){
   36     function fixedFromCharCode(code) {
   37         // String.prototype.fromCharCode does not supports
   38         // > 2 bytes unicode chars directly
   39         if (code > 0xffff) {
   40             code -= 0x10000;
   41             var surrogate1 = 0xd800 + (code >> 10)
   42                 , surrogate2 = 0xdc00 + (code & 0x3ff);
   43 
   44             return String.fromCharCode(surrogate1, surrogate2);
   45         } else {
   46             return String.fromCharCode(code);
   47         }
   48     }
   49     function entityReplacer(a){
   50         var k = a.slice(1,-1);
   51         if(k in entityMap){
   52             return entityMap[k]; 
   53         }else if(k.charAt(0) === '#'){
   54             return fixedFromCharCode(parseInt(k.substr(1).replace('x','0x')))
   55         }else{
   56             errorHandler.error('entity not found:'+a);
   57             return a;
   58         }
   59     }
   60     function appendText(end){//has some bugs
   61         if(end>start){
   62             var xt = source.substring(start,end).replace(/&#?\w+;/g,entityReplacer);
   63             locator&&position(start);
   64             domBuilder.characters(xt,0,end-start);
   65             start = end
   66         }
   67     }
   68     function position(p,m){
   69         while(p>=lineEnd && (m = linePattern.exec(source))){
   70             lineStart = m.index;
   71             lineEnd = lineStart + m[0].length;
   72             locator.lineNumber++;
   73             //console.log('line++:',locator,startPos,endPos)
   74         }
   75         locator.columnNumber = p-lineStart+1;
   76     }
   77     var lineStart = 0;
   78     var lineEnd = 0;
   79     var linePattern = /.*(?:\r\n?|\n)|.*$/g
   80     var locator = domBuilder.locator;
   81     
   82     var parseStack = [{currentNSMap:defaultNSMapCopy}]
   83     var closeMap = {};
   84     var start = 0;
   85     while(true){
   86         try{
   87             var tagStart = source.indexOf('<',start);
   88             if(tagStart<0){
   89                 if(!source.substr(start).match(/^\s*$/)){
   90                     var doc = domBuilder.doc;
   91                     var text = doc.createTextNode(source.substr(start));
   92                     doc.appendChild(text);
   93                     domBuilder.currentElement = text;
   94                 }
   95                 return;
   96             }
   97             if(tagStart>start){
   98                 appendText(tagStart);
   99             }
  100             switch(source.charAt(tagStart+1)){
  101             case '/':
  102                 var end = source.indexOf('>',tagStart+3);
  103                 var tagName = source.substring(tagStart+2,end);
  104                 var config = parseStack.pop();
  105                 if(end<0){
  106                     
  107                     tagName = source.substring(tagStart+2).replace(/[\s<].*/,'');
  108                     //console.error('#@@@@@@'+tagName)
  109                     errorHandler.error("end tag name: "+tagName+' is not complete:'+config.tagName);
  110                     end = tagStart+1+tagName.length;
  111                 }else if(tagName.match(/\s</)){
  112                     tagName = tagName.replace(/[\s<].*/,'');
  113                     errorHandler.error("end tag name: "+tagName+' maybe not complete');
  114                     end = tagStart+1+tagName.length;
  115                 }
  116                 //console.error(parseStack.length,parseStack)
  117                 //console.error(config);
  118                 var localNSMap = config.localNSMap;
  119                 var endMatch = config.tagName == tagName;
  120                 var endIgnoreCaseMach = endMatch || config.tagName&&config.tagName.toLowerCase() == tagName.toLowerCase()
  121                 if(endIgnoreCaseMach){
  122                     domBuilder.endElement(config.uri,config.localName,tagName);
  123                     if(localNSMap){
  124                         for(var prefix in localNSMap){
  125                             domBuilder.endPrefixMapping(prefix) ;
  126                         }
  127                     }
  128                     if(!endMatch){
  129                         errorHandler.fatalError("end tag name: "+tagName+' is not match the current start tagName:'+config.tagName );
  130                     }
  131                 }else{
  132                     parseStack.push(config)
  133                 }
  134                 
  135                 end++;
  136                 break;
  137                 // end elment
  138             case '?':// <?...?>
  139                 locator&&position(tagStart);
  140                 end = parseInstruction(source,tagStart,domBuilder);
  141                 break;
  142             case '!':// <!doctype,<![CDATA,<!--
  143                 locator&&position(tagStart);
  144                 end = parseDCC(source,tagStart,domBuilder,errorHandler);
  145                 break;
  146             default:
  147                 locator&&position(tagStart);
  148                 var el = new ElementAttributes();
  149                 var currentNSMap = parseStack[parseStack.length-1].currentNSMap;
  150                 //elStartEnd
  151                 var end = parseElementStartPart(source,tagStart,el,currentNSMap,entityReplacer,errorHandler);
  152                 var len = el.length;
  153                 
  154                 
  155                 if(!el.closed && fixSelfClosed(source,end,el.tagName,closeMap)){
  156                     el.closed = true;
  157                     if(!entityMap.nbsp){
  158                         errorHandler.warning('unclosed xml attribute');
  159                     }
  160                 }
  161                 if(locator && len){
  162                     var locator2 = copyLocator(locator,{});
  163                     //try{//attribute position fixed
  164                     for(var i = 0;i<len;i++){
  165                         var a = el[i];
  166                         position(a.offset);
  167                         a.locator = copyLocator(locator,{});
  168                     }
  169                     //}catch(e){console.error('@@@@@'+e)}
  170                     domBuilder.locator = locator2
  171                     if(appendElement(el,domBuilder,currentNSMap)){
  172                         parseStack.push(el)
  173                     }
  174                     domBuilder.locator = locator;
  175                 }else{
  176                     if(appendElement(el,domBuilder,currentNSMap)){
  177                         parseStack.push(el)
  178                     }
  179                 }
  180                 
  181                 
  182                 
  183                 if(el.uri === 'http://www.w3.org/1999/xhtml' && !el.closed){
  184                     end = parseHtmlSpecialContent(source,end,el.tagName,entityReplacer,domBuilder)
  185                 }else{
  186                     end++;
  187                 }
  188             }
  189         }catch(e){
  190             errorHandler.error('element parse error: '+e)
  191             //errorHandler.error('element parse error: '+e);
  192             end = -1;
  193             //throw e;
  194         }
  195         if(end>start){
  196             start = end;
  197         }else{
  198             //TODO: 这里有可能sax回退,有位置错误风险
  199             appendText(Math.max(tagStart,start)+1);
  200         }
  201     }
  202 }
  203 function copyLocator(f,t){
  204     t.lineNumber = f.lineNumber;
  205     t.columnNumber = f.columnNumber;
  206     return t;
  207 }
  208 
  209 /**
  210  * @see #appendElement(source,elStartEnd,el,selfClosed,entityReplacer,domBuilder,parseStack);
  211  * @return end of the elementStartPart(end of elementEndPart for selfClosed el)
  212  */
  213 function parseElementStartPart(source,start,el,currentNSMap,entityReplacer,errorHandler){
  214     var attrName;
  215     var value;
  216     var p = ++start;
  217     var s = S_TAG;//status
  218     while(true){
  219         var c = source.charAt(p);
  220         switch(c){
  221         case '=':
  222             if(s === S_ATTR){//attrName
  223                 attrName = source.slice(start,p);
  224                 s = S_EQ;
  225             }else if(s === S_ATTR_SPACE){
  226                 s = S_EQ;
  227             }else{
  228                 //fatalError: equal must after attrName or space after attrName
  229                 throw new Error('attribute equal must after attrName');
  230             }
  231             break;
  232         case '\'':
  233         case '"':
  234             if(s === S_EQ || s === S_ATTR //|| s == S_ATTR_SPACE
  235                 ){//equal
  236                 if(s === S_ATTR){
  237                     errorHandler.warning('attribute value must after "="')
  238                     attrName = source.slice(start,p)
  239                 }
  240                 start = p+1;
  241                 p = source.indexOf(c,start)
  242                 if(p>0){
  243                     value = source.slice(start,p).replace(/&#?\w+;/g,entityReplacer);
  244                     el.add(attrName,value,start-1);
  245                     s = S_ATTR_END;
  246                 }else{
  247                     //fatalError: no end quot match
  248                     throw new Error('attribute value no end \''+c+'\' match');
  249                 }
  250             }else if(s == S_ATTR_NOQUOT_VALUE){
  251                 value = source.slice(start,p).replace(/&#?\w+;/g,entityReplacer);
  252                 //console.log(attrName,value,start,p)
  253                 el.add(attrName,value,start);
  254                 //console.dir(el)
  255                 errorHandler.warning('attribute "'+attrName+'" missed start quot('+c+')!!');
  256                 start = p+1;
  257                 s = S_ATTR_END
  258             }else{
  259                 //fatalError: no equal before
  260                 throw new Error('attribute value must after "="');
  261             }
  262             break;
  263         case '/':
  264             switch(s){
  265             case S_TAG:
  266                 el.setTagName(source.slice(start,p));
  267             case S_ATTR_END:
  268             case S_TAG_SPACE:
  269             case S_TAG_CLOSE:
  270                 s =S_TAG_CLOSE;
  271                 el.closed = true;
  272             case S_ATTR_NOQUOT_VALUE:
  273             case S_ATTR:
  274             case S_ATTR_SPACE:
  275                 break;
  276             //case S_EQ:
  277             default:
  278                 throw new Error("attribute invalid close char('/')")
  279             }
  280             break;
  281         case ''://end document
  282             //throw new Error('unexpected end of input')
  283             errorHandler.error('unexpected end of input');
  284             if(s == S_TAG){
  285                 el.setTagName(source.slice(start,p));
  286             }
  287             return p;
  288         case '>':
  289             switch(s){
  290             case S_TAG:
  291                 el.setTagName(source.slice(start,p));
  292             case S_ATTR_END:
  293             case S_TAG_SPACE:
  294             case S_TAG_CLOSE:
  295                 break;//normal
  296             case S_ATTR_NOQUOT_VALUE://Compatible state
  297             case S_ATTR:
  298                 value = source.slice(start,p);
  299                 if(value.slice(-1) === '/'){
  300                     el.closed  = true;
  301                     value = value.slice(0,-1)
  302                 }
  303             case S_ATTR_SPACE:
  304                 if(s === S_ATTR_SPACE){
  305                     value = attrName;
  306                 }
  307                 if(s == S_ATTR_NOQUOT_VALUE){
  308                     errorHandler.warning('attribute "'+value+'" missed quot(")!!');
  309                     el.add(attrName,value.replace(/&#?\w+;/g,entityReplacer),start)
  310                 }else{
  311                     if(currentNSMap[''] !== 'http://www.w3.org/1999/xhtml' || !value.match(/^(?:disabled|checked|selected)$/i)){
  312                         errorHandler.warning('attribute "'+value+'" missed value!! "'+value+'" instead!!')
  313                     }
  314                     el.add(value,value,start)
  315                 }
  316                 break;
  317             case S_EQ:
  318                 throw new Error('attribute value missed!!');
  319             }
  320 //          console.log(tagName,tagNamePattern,tagNamePattern.test(tagName))
  321             return p;
  322         /*xml space '\x20' | #x9 | #xD | #xA; */
  323         case '\u0080':
  324             c = ' ';
  325         default:
  326             if(c<= ' '){//space
  327                 switch(s){
  328                 case S_TAG:
  329                     el.setTagName(source.slice(start,p));//tagName
  330                     s = S_TAG_SPACE;
  331                     break;
  332                 case S_ATTR:
  333                     attrName = source.slice(start,p)
  334                     s = S_ATTR_SPACE;
  335                     break;
  336                 case S_ATTR_NOQUOT_VALUE:
  337                     var value = source.slice(start,p).replace(/&#?\w+;/g,entityReplacer);
  338                     errorHandler.warning('attribute "'+value+'" missed quot(")!!');
  339                     el.add(attrName,value,start)
  340                 case S_ATTR_END:
  341                     s = S_TAG_SPACE;
  342                     break;
  343                 //case S_TAG_SPACE:
  344                 //case S_EQ:
  345                 //case S_ATTR_SPACE:
  346                 //  void();break;
  347                 //case S_TAG_CLOSE:
  348                     //ignore warning
  349                 }
  350             }else{//not space
  351 //S_TAG,    S_ATTR, S_EQ,   S_ATTR_NOQUOT_VALUE
  352 //S_ATTR_SPACE, S_ATTR_END, S_TAG_SPACE, S_TAG_CLOSE
  353                 switch(s){
  354                 //case S_TAG:void();break;
  355                 //case S_ATTR:void();break;
  356                 //case S_ATTR_NOQUOT_VALUE:void();break;
  357                 case S_ATTR_SPACE:
  358                     var tagName =  el.tagName;
  359                     if(currentNSMap[''] !== 'http://www.w3.org/1999/xhtml' || !attrName.match(/^(?:disabled|checked|selected)$/i)){
  360                         errorHandler.warning('attribute "'+attrName+'" missed value!! "'+attrName+'" instead2!!')
  361                     }
  362                     el.add(attrName,attrName,start);
  363                     start = p;
  364                     s = S_ATTR;
  365                     break;
  366                 case S_ATTR_END:
  367                     errorHandler.warning('attribute space is required"'+attrName+'"!!')
  368                 case S_TAG_SPACE:
  369                     s = S_ATTR;
  370                     start = p;
  371                     break;
  372                 case S_EQ:
  373                     s = S_ATTR_NOQUOT_VALUE;
  374                     start = p;
  375                     break;
  376                 case S_TAG_CLOSE:
  377                     throw new Error("elements closed character '/' and '>' must be connected to");
  378                 }
  379             }
  380         }//end outer switch
  381         //console.log('p++',p)
  382         p++;
  383     }
  384 }
  385 /**
  386  * @return true if has new namespace define
  387  */
  388 function appendElement(el,domBuilder,currentNSMap){
  389     var tagName = el.tagName;
  390     var localNSMap = null;
  391     //var currentNSMap = parseStack[parseStack.length-1].currentNSMap;
  392     var i = el.length;
  393     while(i--){
  394         var a = el[i];
  395         var qName = a.qName;
  396         var value = a.value;
  397         var nsp = qName.indexOf(':');
  398         if(nsp>0){
  399             var prefix = a.prefix = qName.slice(0,nsp);
  400             var localName = qName.slice(nsp+1);
  401             var nsPrefix = prefix === 'xmlns' && localName
  402         }else{
  403             localName = qName;
  404             prefix = null
  405             nsPrefix = qName === 'xmlns' && ''
  406         }
  407         //can not set prefix,because prefix !== ''
  408         a.localName = localName ;
  409         //prefix == null for no ns prefix attribute 
  410         if(nsPrefix !== false){//hack!!
  411             if(localNSMap == null){
  412                 localNSMap = {}
  413                 //console.log(currentNSMap,0)
  414                 _copy(currentNSMap,currentNSMap={})
  415                 //console.log(currentNSMap,1)
  416             }
  417             currentNSMap[nsPrefix] = localNSMap[nsPrefix] = value;
  418             a.uri = 'http://www.w3.org/2000/xmlns/'
  419             domBuilder.startPrefixMapping(nsPrefix, value) 
  420         }
  421     }
  422     var i = el.length;
  423     while(i--){
  424         a = el[i];
  425         var prefix = a.prefix;
  426         if(prefix){//no prefix attribute has no namespace
  427             if(prefix === 'xml'){
  428                 a.uri = 'http://www.w3.org/XML/1998/namespace';
  429             }if(prefix !== 'xmlns'){
  430                 a.uri = currentNSMap[prefix || '']
  431                 
  432                 //{console.log('###'+a.qName,domBuilder.locator.systemId+'',currentNSMap,a.uri)}
  433             }
  434         }
  435     }
  436     var nsp = tagName.indexOf(':');
  437     if(nsp>0){
  438         prefix = el.prefix = tagName.slice(0,nsp);
  439         localName = el.localName = tagName.slice(nsp+1);
  440     }else{
  441         prefix = null;//important!!
  442         localName = el.localName = tagName;
  443     }
  444     //no prefix element has default namespace
  445     var ns = el.uri = currentNSMap[prefix || ''];
  446     domBuilder.startElement(ns,localName,tagName,el);
  447     //endPrefixMapping and startPrefixMapping have not any help for dom builder
  448     //localNSMap = null
  449     if(el.closed){
  450         domBuilder.endElement(ns,localName,tagName);
  451         if(localNSMap){
  452             for(prefix in localNSMap){
  453                 domBuilder.endPrefixMapping(prefix) 
  454             }
  455         }
  456     }else{
  457         el.currentNSMap = currentNSMap;
  458         el.localNSMap = localNSMap;
  459         //parseStack.push(el);
  460         return true;
  461     }
  462 }
  463 function parseHtmlSpecialContent(source,elStartEnd,tagName,entityReplacer,domBuilder){
  464     if(/^(?:script|textarea)$/i.test(tagName)){
  465         var elEndStart =  source.indexOf('</'+tagName+'>',elStartEnd);
  466         var text = source.substring(elStartEnd+1,elEndStart);
  467         if(/[&<]/.test(text)){
  468             if(/^script$/i.test(tagName)){
  469                 //if(!/\]\]>/.test(text)){
  470                     //lexHandler.startCDATA();
  471                     domBuilder.characters(text,0,text.length);
  472                     //lexHandler.endCDATA();
  473                     return elEndStart;
  474                 //}
  475             }//}else{//text area
  476                 text = text.replace(/&#?\w+;/g,entityReplacer);
  477                 domBuilder.characters(text,0,text.length);
  478                 return elEndStart;
  479             //}
  480             
  481         }
  482     }
  483     return elStartEnd+1;
  484 }
  485 function fixSelfClosed(source,elStartEnd,tagName,closeMap){
  486     //if(tagName in closeMap){
  487     var pos = closeMap[tagName];
  488     if(pos == null){
  489         //console.log(tagName)
  490         pos =  source.lastIndexOf('</'+tagName+'>')
  491         if(pos<elStartEnd){//忘记闭合
  492             pos = source.lastIndexOf('</'+tagName)
  493         }
  494         closeMap[tagName] =pos
  495     }
  496     return pos<elStartEnd;
  497     //} 
  498 }
  499 function _copy(source,target){
  500     for(var n in source){target[n] = source[n]}
  501 }
  502 function parseDCC(source,start,domBuilder,errorHandler){//sure start with '<!'
  503     var next= source.charAt(start+2)
  504     switch(next){
  505     case '-':
  506         if(source.charAt(start + 3) === '-'){
  507             var end = source.indexOf('-->',start+4);
  508             //append comment source.substring(4,end)//<!--
  509             if(end>start){
  510                 domBuilder.comment(source,start+4,end-start-4);
  511                 return end+3;
  512             }else{
  513                 errorHandler.error("Unclosed comment");
  514                 return -1;
  515             }
  516         }else{
  517             //error
  518             return -1;
  519         }
  520     default:
  521         if(source.substr(start+3,6) == 'CDATA['){
  522             var end = source.indexOf(']]>',start+9);
  523             domBuilder.startCDATA();
  524             domBuilder.characters(source,start+9,end-start-9);
  525             domBuilder.endCDATA() 
  526             return end+3;
  527         }
  528         //<!DOCTYPE
  529         //startDTD(java.lang.String name, java.lang.String publicId, java.lang.String systemId) 
  530         var matchs = split(source,start);
  531         var len = matchs.length;
  532         if(len>1 && /!doctype/i.test(matchs[0][0])){
  533             var name = matchs[1][0];
  534             var pubid = len>3 && /^public$/i.test(matchs[2][0]) && matchs[3][0]
  535             var sysid = len>4 && matchs[4][0];
  536             var lastMatch = matchs[len-1]
  537             domBuilder.startDTD(name,pubid && pubid.replace(/^(['"])(.*?)\1$/,'$2'),
  538                     sysid && sysid.replace(/^(['"])(.*?)\1$/,'$2'));
  539             domBuilder.endDTD();
  540             
  541             return lastMatch.index+lastMatch[0].length
  542         }
  543     }
  544     return -1;
  545 }
  546 
  547 
  548 
  549 function parseInstruction(source,start,domBuilder){
  550     var end = source.indexOf('?>',start);
  551     if(end){
  552         var match = source.substring(start,end).match(/^<\?(\S*)\s*([\s\S]*?)\s*$/);
  553         if(match){
  554             var len = match[0].length;
  555             domBuilder.processingInstruction(match[1], match[2]) ;
  556             return end+2;
  557         }else{//error
  558             return -1;
  559         }
  560     }
  561     return -1;
  562 }
  563 
  564 /**
  565  * @param source
  566  */
  567 function ElementAttributes(source){
  568     
  569 }
  570 ElementAttributes.prototype = {
  571     setTagName:function(tagName){
  572         if(!tagNamePattern.test(tagName)){
  573             throw new Error('invalid tagName:'+tagName)
  574         }
  575         this.tagName = tagName
  576     },
  577     add:function(qName,value,offset){
  578         if(!tagNamePattern.test(qName)){
  579             throw new Error('invalid attribute:'+qName)
  580         }
  581         this[this.length++] = {qName:qName,value:value,offset:offset}
  582     },
  583     length:0,
  584     getLocalName:function(i){return this[i].localName},
  585     getLocator:function(i){return this[i].locator},
  586     getQName:function(i){return this[i].qName},
  587     getURI:function(i){return this[i].uri},
  588     getValue:function(i){return this[i].value}
  589 //  ,getIndex:function(uri, localName)){
  590 //      if(localName){
  591 //          
  592 //      }else{
  593 //          var qName = uri
  594 //      }
  595 //  },
  596 //  getValue:function(){return this.getValue(this.getIndex.apply(this,arguments))},
  597 //  getType:function(uri,localName){}
  598 //  getType:function(i){},
  599 }
  600 
  601 
  602 
  603 
  604 function _set_proto_(thiz,parent){
  605     thiz.__proto__ = parent;
  606     return thiz;
  607 }
  608 if(!(_set_proto_({},_set_proto_.prototype) instanceof _set_proto_)){
  609     _set_proto_ = function(thiz,parent){
  610         function p(){};
  611         p.prototype = parent;
  612         p = new p();
  613         for(parent in thiz){
  614             p[parent] = thiz[parent];
  615         }
  616         return p;
  617     }
  618 }
  619 
  620 function split(source,start){
  621     var match;
  622     var buf = [];
  623     var reg = /'[^']+'|"[^"]+"|[^\s<>\/=]+=?|(\/?\s*>|<)/g;
  624     reg.lastIndex = start;
  625     reg.exec(source);//skip <
  626     while(match = reg.exec(source)){
  627         buf.push(match);
  628         if(match[1])return buf;
  629     }
  630 }
  631 
  632 exports.XMLReader = XMLReader;
  633