PageSourceSearch

https://ikusapo.com/js/jkl-parsexml.js

js ikusapo.com collected 2026-10-05 03:46:28 UTC 25,288 bytes, 666 lines download raw bytes

1// ================================================================
2//  jkl-parsexml.js ---- JavaScript Kantan Library for Parse XML
3//  Copyright 2005-2006 Kawasaki Yusuke <[email protected]>
4//  http://www.kawa.net/works/js/jkl/parsexml.html
5// ================================================================
6//  v0.01  2005/05/18  first release
7//  v0.02  2005/05/20  Opera 8.0beta may be abailable but somtimes crashed
8//  v0.03  2005/05/20  overrideMimeType( "text/xml" );
9//  v0.04  2005/05/21  class variables: REQUEST_TYPE, RESPONSE_TYPE
10//  v0.05  2005/05/22  use Msxml2.DOMDocument.5.0 for GET method on IE6
11//  v0.06  2005/05/22  CDATA_SECTION_NODE
12//  v0.07  2005/05/23  use Microsoft.XMLDOM for GET method on IE6
13//  v0.10  2005/10/11  new function: JKL.ParseXML.HTTP.responseText()
14//  v0.11  2005/10/13  new sub class: JKL.ParseXML.Text, JSON and DOM.
15//  v0.12  2005/10/14  new sub class: JKL.ParseXML.CSV and CSVmap.
16//  v0.13  2005/10/28  bug fixed: TEXT_NODE regexp for white spaces
17//  v0.14  2005/11/06  bug fixed: TEXT_NODE regexp at Safari
18//  v0.15  2005/11/08  bug fixed: JKL.ParseXML.CSV.async() method
19//  v0.16  2005/11/15  new sub class: LoadVars, and UTF-8 text on Safari
20//  v0.18  2005/11/16  improve: UTF-8 text file on Safari
21//  v0.19  2006/02/03  use XMLHTTPRequest instead of ActiveX on IE7,iCab
22// ================================================================
23
24if ( typeof(JKL) == 'undefined' ) JKL = function() {};
25
26// ================================================================
27//  class: JKL.ParseXML 
28
29JKL.ParseXML = function ( url, query, method ) {
30    // debug.print( "new JKL.ParseXML( '"+url+"', '"+query+"', '"+method+"' );" );
31    this.http = new JKL.ParseXML.HTTP( url, query, method, false );
32    return this;
33};
34
35// ================================================================
36//  class variables
37
38JKL.ParseXML.VERSION = "0.19";
39JKL.ParseXML.MIME_TYPE_XML  = "text/xml";
40JKL.ParseXML.MAP_NODETYPE = [
41    "",
42    "ELEMENT_NODE",                 // 1
43    "ATTRIBUTE_NODE",               // 2
44    "TEXT_NODE",                    // 3
45    "CDATA_SECTION_NODE",           // 4
46    "ENTITY_REFERENCE_NODE",        // 5
47    "ENTITY_NODE",                  // 6
48    "PROCESSING_INSTRUCTION_NODE",  // 7
49    "COMMENT_NODE",                 // 8
50    "DOCUMENT_NODE",                // 9
51    "DOCUMENT_TYPE_NODE",           // 10
52    "DOCUMENT_FRAGMENT_NODE",       // 11
53    "NOTATION_NODE"                 // 12
54];
55
56// ================================================================
57//  define callback function (ajax)
58
59JKL.ParseXML.prototype.async = function ( func, args ) {
60    this.callback_func = func;      // callback function
61    this.callback_arg  = args;      // first argument
62};
63
64JKL.ParseXML.prototype.onerror = function ( func, args ) {
65    this.onerror_func = func;       // callback function
66};
67
68// ================================================================
69//  method: parse()
70//  return: parsed object
71//  Download a file from remote server and parse it.
72
73JKL.ParseXML.prototype.parse = function () {
74    if ( ! this.http ) return;
75
76    // set onerror call back 
77    if ( this.onerror_func ) {
78        this.http.onerror( this.onerror_func );
79    }
80
81    if ( this.callback_func ) {                             // async mode
82        var copy = this;
83        var proc = function() {
84            if ( ! copy.http ) return;
85            var data = copy.parseResponse();
86            copy.callback_func( data, copy.callback_arg );  // call back
87        };
88        this.http.async( proc );
89    }
90
91    this.http.load();
92
93    if ( ! this.callback_func ) {                           // sync mode
94        var data = this.parseResponse();
95        return data;
96    }
97};
98
99// ================================================================
100//  every child/children into array
101JKL.ParseXML.prototype.setOutputArrayAll = function () {
102    this.setOutputArray( true );
103}
104//  a child into scalar, children into array
105JKL.ParseXML.prototype.setOutputArrayAuto = function () {
106    this.setOutputArray( null );
107}
108//  every child/children into scalar (first sibiling only)
109JKL.ParseXML.prototype.setOutputArrayNever = function () {
110    this.setOutputArray( false );
111}
112//  specified child/children into array, other child/children into scalar
113JKL.ParseXML.prototype.setOutputArrayElements = function ( list ) {
114    this.setOutputArray( list );
115}
116//  specify how to treate child/children into scalar/array
117JKL.ParseXML.prototype.setOutputArray = function ( mode ) {
118    if ( typeof(mode) == "string" ) {
119        mode = [ mode ];                // string into array
120    }
121    if ( mode && typeof(mode) == "object" ) {
122        if ( mode.length < 0 ) {
123            mode = false;               // false when array == [] 
124        } else {
125            var hash = {};
126            for( var i=0; i<mode.length; i++ ) {
127                hash[mode[i]] = true;
128            }
129            mode = hash;                // array into hashed array
130            if ( mode["*"] ) {
131                mode = true;            // true when includes "*"
132            }
133        } 
134    } 
135    this.usearray = mode;
136}
137
138// ================================================================
139//  method: parseResponse()
140
141JKL.ParseXML.prototype.parseResponse = function () {
142    var root = this.http.documentElement();
143    var data = this.parseDocument( root );
144    return data;
145}
146
147// ================================================================
148//  convert from DOM root node to JavaScript Object 
149//  method: parseElement( rootElement )
150
151JKL.ParseXML.prototype.parseDocument = function ( root ) {
152    // debug.print( "parseDocument: "+root );
153    if ( ! root ) return;
154
155    var ret = this.parseElement( root );            // parse root node
156    // debug.print( "parsed: "+ret );
157
158    if ( this.usearray == true ) {                  // always into array
159        ret = [ ret ];
160    } else if ( this.usearray == false ) {          // always into scalar
161        //
162    } else if ( this.usearray == null ) {           // automatic
163        //
164    } else if ( this.usearray[root.nodeName] ) {    // specified tag
165        ret = [ ret ];
166    }
167
168    var json = {};
169    json[root.nodeName] = ret;                      // root nodeName
170    return json;
171};
172
173// ================================================================
174//  convert from DOM Element to JavaScript Object 
175//  method: parseElement( element )
176
177JKL.ParseXML.prototype.parseElement = function ( elem ) {
178    // debug.print( "nodeType: "+JKL.ParseXML.MAP_NODETYPE[elem.nodeType]+" <"+elem.nodeName+">" );
179
180    //  COMMENT_NODE
181
182    if ( elem.nodeType == 7 ) {
183        return;
184    }
185
186    //  TEXT_NODE CDATA_SECTION_NODE
187
188    if ( elem.nodeType == 3 || elem.nodeType == 4 ) {
189        // var bool = elem.nodeValue.match( /[^\u0000-\u0020]/ );
190        var bool = elem.nodeValue.match( /[^\x00-\x20]/ ); // for Safari
191        if ( bool == null ) return;
191     // ignore white spaces
192        // debug.print( "TEXT_NODE: "+elem.nodeValue.length+ " "+bool );
193        return elem.nodeValue;
194    }
195
196    var retval;
197    var cnt = {};
198
199    //  parse attributes
200
201    if ( elem.attributes && elem.attributes.length ) {
202        retval = {};
203        for ( var i=0; i<elem.attributes.length; i++ ) {
204            var key = elem.attributes[i].nodeName;
205            if ( typeof(key) != "string" ) continue;
206            var val = elem.attributes[i].nodeValue;
207            if ( ! val ) continue;
208            if ( typeof(cnt[key]) == "undefined" ) cnt[key] = 0;
209            cnt[key] ++;
210            this.addNode( retval, key, cnt[key], val );
211        }
212    }
213
214    //  parse child nodes (recursive)
215
216    if ( elem.childNodes && elem.childNodes.length ) {
217        var textonly = true;
218        if ( retval ) textonly = false;        // some attributes exists
219        for ( var i=0; i<elem.childNodes.length && textonly; i++ ) {
220            var ntype = elem.childNodes[i].nodeType;
221            if ( ntype == 3 || ntype == 4 ) continue;
222            textonly = false;
223        }
224        if ( textonly ) {
225            if ( ! retval ) retval = "";
226            for ( var i=0; i<elem.childNodes.length; i++ ) {
227                retval += elem.childNodes[i].nodeValue;
228            }
229        } else {
230            if ( ! retval ) retval = {};
231            for ( var i=0; i<elem.childNodes.length; i++ ) {
232                var key = elem.childNodes[i].nodeName;
233                if ( typeof(key) != "string" ) continue;
234                var val = this.parseElement( elem.childNodes[i] );
235                if ( ! val ) continue;
236                if ( typeof(cnt[key]) == "undefined" ) cnt[key] = 0;
237                cnt[key] ++;
238                this.addNode( retval, key, cnt[key], val );
239            }
240        }
241    }
242    return retval;
243};
244
245// ================================================================
246//  method: addNode( hash, key, count, value )
247
248JKL.ParseXML.prototype.addNode = function ( hash, key, cnts, val ) {
249    if ( this.usearray == true ) {              // into array
250        if ( cnts == 1 ) hash[key] = [];
251        hash[key][hash[key].length] = val;      // push
252    } else if ( this.usearray == false ) {      // into scalar
253        if ( cnts == 1 ) hash[key] = val;       // only 1st sibling
254    } else if ( this.usearray == null ) {
255        if ( cnts == 1 ) {                      // 1st sibling
256            hash[key] = val;
257        } else if ( cnts == 2 ) {               // 2nd sibling
258            hash[key] = [ hash[key], val ];
259        } else {                                // 3rd sibling and more
260            hash[key][hash[key].length] = val;
261        }
262    } else if ( this.usearray[key] ) {
263        if ( cnts == 1 ) hash[key] = [];
264        hash[key][hash[key].length] = val;      // push
265    } else {
266        if ( cnts == 1 ) hash[key] = val;       // only 1st sibling
267    }
268};
269
270// ================================================================
271//  class: JKL.ParseXML.Text 
272
273JKL.ParseXML.Text = function ( url, query, method ) {
274    // debug.print( "new JKL.ParseXML.Text( '"+url+"', '"+query+"', '"+method+"' );" );
275    this.http = new JKL.ParseXML.HTTP( url, query, method, true );
276    return this;
277};
278
279JKL.ParseXML.Text.prototype.parse = JKL.ParseXML.prototype.parse;
280JKL.ParseXML.Text.prototype.async = JKL.ParseXML.prototype.async;
281
282JKL.ParseXML.Text.prototype.parseResponse = function () {
283    var data = this.http.responseText();
284    return data;
285}
286
287// ================================================================
288//  class: JKL.ParseXML.JSON
289
290JKL.ParseXML.JSON = function ( url, query, method ) {
291    // debug.print( "new JKL.ParseXML.JSON( '"+url+"', '"+query+"', '"+method+"' );" );
292    this.http = new JKL.ParseXML.HTTP( url, query, method, true );
293    return this;
294};
295
296JKL.ParseXML.JSON.prototype.parse = JKL.ParseXML.prototype.parse;
297JKL.ParseXML.JSON.prototype.async = JKL.ParseXML.prototype.async;
298
299JKL.ParseXML.JSON.prototype.parseResponse = function () {
300    var text = this.http.responseText();
301    var data = eval( "("+text+")" );
302    return data;
303}
304
305// ================================================================
306//  class: JKL.ParseXML.DOM
307
308JKL.ParseXML.DOM = function ( url, query, method ) {
309    // debug.print( "new JKL.ParseXML.DOM( '"+url+"', '"+query+"', '"+method+"' );" );
310    this.http = new JKL.ParseXML.HTTP( url, query, method, false );
311    return this;
312};
313
314JKL.ParseXML.DOM.prototype.parse = JKL.ParseXML.prototype.parse;
315JKL.ParseXML.DOM.prototype.async = JKL.ParseXML.prototype.async;
316
317JKL.ParseXML.DOM.prototype.parseResponse = function () {
318    var data = this.http.documentElement();
319    return data;
320}
321
322// ================================================================
323//  class: JKL.ParseXML.CSV
324
325JKL.ParseXML.CSV = function ( url, query, method ) {
326    // debug.print( "new JKL.ParseXML.CSV( '"+url+"', '"+query+"', '"+method+"' );" );
327    this.http = new JKL.ParseXML.HTTP( url, query, method, true );
328    return this;
329};
330
331JKL.ParseXML.CSV.prototype.parse = JKL.ParseXML.prototype.parse;
332JKL.ParseXML.CSV.prototype.async = JKL.ParseXML.prototype.async;
333
334JKL.ParseXML.CSV.prototype.parseResponse = function () {
335    var text = this.http.responseText();
336    var data = this.parseCSV( text );
337    return data;
338}
339
340JKL.ParseXML.CSV.prototype.parseCSV = function ( text ) {
341    text = text.replace( /\r\n?/g, "\n" );              // new line character
342    var pos = 0;
343    var len = text.length;
344    var table = [];
345    while( pos<len ) {
346        var line = [];
347        while( pos<len ) {
348            if ( text.charAt(pos) == '"' ) {            // "..." quoted column
349                var nextquote = text.indexOf( '"', pos+1 );
350                while ( nextquote<len && nextquote > -1 ) {
351                    if ( text.charAt(nextquote+1) != '"' ) {
352                        break;                          // end of column
353                    }
354                    nextquote = text.indexOf( '"', nextquote+2 );
355                }
356                if ( nextquote < 0 ) {
357                    // unclosed quote
358                } else if ( text.charAt(nextquote+1) == "," ) { // end of column
359                    var quoted = text.substr( pos+1, nextquote-pos-1 );
360                    quoted = quoted.replace(/""/g,'"');
361                    line[line.length] = quoted;
362                    pos = nextquote+2;
363                    continue;
364                } else if ( text.charAt(nextquote+1) == "\n" || // end of line
365                            len==nextquote+1 ) {                // end of file
366                    var quoted = text.substr( pos+1, nextquote-pos-1 );
367                    quoted = quoted.replace(/""/g,'"');
368                    line[line.length] = quoted;
369                    pos = nextquote+2;
370                    break;
371                } else {
372                    // invalid column
373                }
374            }
375            var nextcomma = text.indexOf( ",", pos );
376            var nextnline = text.indexOf( "\n", pos );
377            if ( nextnline < 0 ) nextnline = len;
378            if ( nextcomma > -1 && nextcomma < nextnline ) {
379                line[line.length] = text.substr( pos, nextcomma-pos );
380                pos = nextcomma+1;
381            } else {                                    // end of line
382                line[line.length] = text.substr( pos, nextnline-pos );
383                pos = nextnline+1;
384                break;
385            }
386        }
387        if ( line.length >= 0 ) {
388            table[table.length] = line;                 // push line
389        }
390    }
391    if ( table.length < 0 ) return;                     // null data
392    return table;
393};
394
395// ================================================================
396//  class: JKL.ParseXML.CSVmap
397
398JKL.ParseXML.CSVmap = function ( url, query, method ) {
399    // debug.print( "new JKL.ParseXML.CSVmap( '"+url+"', '"+query+"', '"+method+"' );" );
400    this.http = new JKL.ParseXML.HTTP( url, query, method, true );
401    return this;
402};
403
404JKL.ParseXML.CSVmap.prototype.parse = JKL.ParseXML.prototype.parse;
405JKL.ParseXML.CSVmap.prototype.async = JKL.ParseXML.prototype.async;
406JKL.ParseXML.CSVmap.prototype.parseCSV = JKL.ParseXML.CSV.prototype.parseCSV;
407
408JKL.ParseXML.CSVmap.prototype.parseResponse = function () {
409    var text = this.http.responseText();
410    var source = this.parseCSV( text );
411    if ( ! source ) return;
412    if ( source.length < 0 ) return;
413
414    var title = source.shift();                 // first line as title
415    var data = [];
416    for( var i=0; i<source.length; i++ ) {
417        var hash = {};
418        for( var j=0; j<title.length && j<source[i].length; j++ ) {
419            hash[title[j]] = source[i][j];      // array to map
420        }
421        data[data.length] = hash;               // push line
422    }
423    return data;
424}
425
426// ================================================================
427//  class: JKL.ParseXML.LoadVars
428
429JKL.ParseXML.LoadVars = function ( url, query, method ) {
430    // debug.print( "new JKL.ParseXML.LoadVars( '"+url+"', '"+query+"', '"+method+"' );" );
431    this.http = new JKL.ParseXML.HTTP( url, query, method, true );
432    return this;
433};
434
435JKL.ParseXML.LoadVars.prototype.parse = JKL.ParseXML.prototype.parse;
436JKL.ParseXML.LoadVars.prototype.async = JKL.ParseXML.prototype.async;
437
438JKL.ParseXML.LoadVars.prototype.parseResponse = function () {
439    var text = this.http.responseText();
440    text = text.replace( /\r\n?/g, "\n" );              // new line character
441    var hash = {};
442    var list = text.split( "&" );
443    for( var i=0; i<list.length; i++ ) {
444        var eq = list[i].indexOf( "=" );
445        if ( eq > -1 ) {
446            var key = decodeURIComponent(list[i].substr(0,eq).replace("+","%20"));
447            var val = decodeURIComponent(list[i].substr(eq+1).replace("+","%20"));
448            hash[key] = val;
449        } else {
450            hash[list[i]] = "";
451        }
452    }
453    return hash;
454};
455
456// ================================================================
457//  class: JKL.ParseXML.HTTP
458//  constructer: new JKL.ParseXML.HTTP()
459
460JKL.ParseXML.HTTP = function( url, query, method, textmode ) {
461    // debug.print( "new JKL.ParseXML.HTTP( '"+url+"', '"+query+"', '"+method+"', '"+textmode+"' );" );
462    this.url = url;
463    if ( typeof(query) == "string" ) {
464        this.query = query;
465    } else {
466        this.query = "";
467    }
468    if ( method ) {
469        this.method = method;
470    } else if ( typeof(query) == "string" ) {
471        this.method = "POST";
472    } else {
473        this.method = "GET";
474    }
475    this.textmode = textmode ? true : false;
476    this.req = null;
477    this.xmldom_flag = false;
478    this.onerror_func  = null;
479    this.callback_func = null;
480    this.already_done = null;
481    return this;
482};
483
484// ================================================================
485//  class variables
486
487JKL.ParseXML.HTTP.REQUEST_TYPE  = "application/x-www-form-urlencoded";
488JKL.ParseXML.HTTP.ACTIVEX_XMLDOM  = "Microsoft.XMLDOM";  // Msxml2.DOMDocument.5.0
489JKL.ParseXML.HTTP.ACTIVEX_XMLHTTP = "Microsoft.XMLHTTP"; // Msxml2.XMLHTTP.3.0
490JKL.ParseXML.HTTP.EPOCH_TIMESTAMP = "Thu, 01 Jun 1970 00:00:00 GMT"
491
492// ================================================================
493
494JKL.ParseXML.HTTP.prototype.onerror = function( func ) {
495    this.onerror_func = func;
496}
497JKL.ParseXML.HTTP.prototype.async = function( func ) {
498    this.async_func = func;
499}
500
501// ================================================================
502//  [IE+IXMLDOMElement]
503//      XML     text/xml            OK
504//      XML     application/rdf+xml OK
505//      TEXT    text/plain          NG
506//      TEXT    others              NG
507//  [IE+IXMLHttpRequest]
508//      XML     text/xml            OK
509//      XML     application/rdf+xml NG
510//      TEXT    text/plain          OK
511//      TEXT    others              OK
512//  [Firefox+XMLHttpRequest]
513//      XML     text/xml            OK
514//      XML     application/rdf+xml OK (overrideMimeType)
515//      TEXT    text/plain          OK
516//      TEXT    others              OK (overrideMimeType)
517//  [Opera+XMLHttpRequest]
518//      XML     text/xml            OK
519//      XML     application/rdf+xml OK
520//      TEXT    text/plain          OK
521//      TEXT    others              OK
522// ================================================================
523
524JKL.ParseXML.HTTP.prototype.load = function() {
525    // create XMLHttpRequest object
526    if ( window.XMLHttpRequest ) {              // Firefox, Opera, IE7, iCab
527        // debug.print( "new XMLHttpRequest()" );
528        this.req = new XMLHttpRequest();
529    } else if ( window.ActiveXObject ) {                    // IE5.5/6
530        var activex = JKL.ParseXML.HTTP.ACTIVEX_XMLHTTP;    // IXMLHttpRequest
531        if ( this.method == "GET" && ! this.textmode ) {
532            // use IXMLDOMElement to accept any mime types
533            // because overrideMimeType() is not available on IE6
534            activex = JKL.ParseXML.HTTP.ACTIVEX_XMLDOM;     // IXMLDOMElement
535        }
536        // debug.print( "new ActiveXObject( '"+activex+"' )" );
537        this.req = new ActiveXObject( activex );
538    }
539
540    // async mode when call back function is specified
541    var async_flag = this.async_func ? true : false;
542    // debug.print( "async: "+ async_flag );
543
544    // open for XMLHTTPRequest (not for IXMLDOMElement)
545    if ( typeof(this.req.send) != "undefined" ) {
546        // debug.print( "open( '"+this.method+"', '"+this.url+"', "+async_flag+" );" );
547        this.req.open( this.method, this.url, async_flag );
548    }
549
550//  // If-Modified-Since: Thu, 01 Jun 1970 00:00:00 GMT
551//  if ( typeof(this.req.setRequestHeader) != "undefined" ) {
552//      // debug.print( "If-Modified-Since"+JKL.ParseXML.HTTP.EPOCH_TIMESTAMP );
553//      this.req.setRequestHeader( "If-Modified-Since", JKL.ParseXML.HTTP.EPOCH_TIMESTAMP );
554//  }
555
556    // Content-Type: application/x-www-form-urlencoded (request header)
557    // Some server does not accept without request content-type.
558    if ( typeof(this.req.setRequestHeader) != "undefined" ) {
559        // debug.print( "Content-Type: "+JKL.ParseXML.HTTP.REQUEST_TYPE+" (request)" );
560        this.req.setRequestHeader( "Content-Type", JKL.ParseXML.HTTP.REQUEST_TYPE );
561    }
562
563    // Content-Type: text/xml (response header)
564    // FireFox does not accept other mime types like application/rdf+xml etc.
565    if ( typeof(this.req.overrideMimeType) != "undefined" && ! this.textmode ) {
566        // debug.print( "Content-Type: "+JKL.ParseXML.MIME_TYPE_XML+" (response)" );
567        this.req.overrideMimeType( JKL.ParseXML.MIME_TYPE_XML );
568    }
569
570    // set call back handler when async mode
571    if ( async_flag ) {
572        var copy = this;
573        copy.already_done = false;                  // not parsed yet
574        var check_func = function () {
575            if ( copy.req.readyState != 4 ) return;
576            // debug.print( "readyState(async): "+copy.req.readyState );
577            var succeed = copy.checkResponse();
578            // debug.print( "checkResponse(async): "+succeed );
579            if ( ! succeed ) return;                // failed
580            if ( copy.already_done ) return;        // parse only once
581            copy.already_done = true;               // already parsed
582            copy.async_func();                      // call back async
583        };
584        this.req.onreadystatechange = check_func;
585        // for document.implementation.createDocument
586        // this.req.onload = check_func;
587    }
588
589    // send the request and query string
590    if ( typeof(this.req.send) != "undefined" ) {
591        // debug.print( "XMLHTTPRequest: send( '"+this.query+"' );" );
592        this.req.send( this.query );                        // XMLHTTPRequest
593    } else if ( typeof(this.req.load) != "undefined" ) {
594        // debug.print( "IXMLDOMElement: load( '"+this.url+"' );" );
595        this.req.async = async_flag;
596        this.req.load( this.url );                          // IXMLDOMElement
597    }
598
599    // just return when async mode
600    if ( async_flag ) return;
601
602    var succeed = this.checkResponse();
603    // debug.print( "checkResponse(sync): "+succeed );
604}
605
606// ================================================================
607//  method: checkResponse()
608
609JKL.ParseXML.HTTP.prototype.checkResponse = function() {
610    // parseError on IXMLDOMElement
611    if ( this.req.parseError && this.req.parseError.errorCode != 0 ) {
612        // debug.print( "parseError: "+this.req.parseError.reason );
613        if ( this.onerror_func ) this.onerror_func( this.req.parseError.reason );
614        return false;                       // failed
615    }
616
617    // HTTP response code
618    if ( this.req.status-0 > 0 &&
619         this.req.status != 200 &&          // OK
620         this.req.status != 206 &&          // Partial Content
621         this.req.status != 304 ) {         // Not Modified
622        // debug.print( "status: "+this.req.status );
623        if ( this.onerror_func ) this.onerror_func( this.req.status );
624        return false;                       // failed
625    }
626
627    return true;                            // succeed
628}
629
630// ================================================================
631//  method: documentElement()
632//  return: XML DOM in response body
633
634JKL.ParseXML.HTTP.prototype.documentElement = function() {
635    // debug.print( "documentElement: "+this.req );
636    if ( ! this.req ) return;
637    if ( this.req.responseXML ) {
638        return this.req.responseXML.documentElement;    // XMLHTTPRequest
639    } else {
640        return this.req.documentElement;                // IXMLDOMDocument
641    }
642}
643
644// ================================================================
645//  method: responseText()
646//  return: text string in response body
647
648JKL.ParseXML.HTTP.prototype.responseText = function() {
649    // debug.print( "responseText: "+this.req );
650    if ( ! this.req ) return;
651
652    //  Safari and Konqueror cannot understand the encoding of text files.
653    if ( navigator.appVersion.match( "KHTML" ) ) {
654        var esc = escape( this.req.responseText );
655//        debug.print( "escape: "+esc );
656        if ( ! esc.match("%u") && esc.match("%") ) {
657            return decodeURIComponent(esc);
658        }
659    }
660
661    return this.req.responseText;
662}
663
664// ================================================================
665//  http://msdn.microsoft.com/library/en-us/xmlsdk/html/d051f7c5-e882-42e8-a5b6-d1ce67af275c.asp
666// ================================================================

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.