// ================================================================ // jkl-parsexml.js ---- JavaScript Kantan Library for Parsing XML // Copyright 2005-2007 Kawasaki Yusuke // http://www.kawa.net/works/js/jkl/parsexml.html // ================================================================ // v0.01 2005/05/18 first release // v0.02 2005/05/20 Opera 8.0beta may be abailable but somtimes crashed // v0.03 2005/05/20 overrideMimeType( "text/xml" ); // v0.04 2005/05/21 class variables: REQUEST_TYPE, RESPONSE_TYPE // v0.05 2005/05/22 use Msxml2.DOMDocument.5.0 for GET method on IE6 // v0.06 2005/05/22 CDATA_SECTION_NODE // v0.07 2005/05/23 use Microsoft.XMLDOM for GET method on IE6 // v0.10 2005/10/11 new function: JKL.ParseXML.HTTP.responseText() // v0.11 2005/10/13 new sub class: JKL.ParseXML.Text, JSON and DOM. // v0.12 2005/10/14 new sub class: JKL.ParseXML.CSV and CSVmap. // v0.13 2005/10/28 bug fixed: TEXT_NODE regexp for white spaces // v0.14 2005/11/06 bug fixed: TEXT_NODE regexp at Safari // v0.15 2005/11/08 bug fixed: JKL.ParseXML.CSV.async() method // v0.16 2005/11/15 new sub class: LoadVars, and UTF-8 text on Safari // v0.18 2005/11/16 improve: UTF-8 text file on Safari // v0.19 2006/02/03 use XMLHTTPRequest instead of ActiveX on IE7,iCab // v0.20 2006/03/22 (skipped) // v0.21 2006/11/30 use ActiveX again on IE7 // v0.22 2007/01/04 JKL.ParseXML.JSON.parseResponse() updated // ================================================================ if ( typeof(JKL) == 'undefined' ) JKL = function() {}; // ================================================================ // class: JKL.ParseXML JKL.ParseXML = function ( url, query, method ) { // debug.print( "new JKL.ParseXML( '"+url+"', '"+query+"', '"+method+"' );" ); this.http = new JKL.ParseXML.HTTP( url, query, method, false ); return this; }; // ================================================================ // class variables JKL.ParseXML.VERSION = "0.22"; JKL.ParseXML.MIME_TYPE_XML = "text/xml"; JKL.ParseXML.MAP_NODETYPE = [ "", "ELEMENT_NODE", // 1 "ATTRIBUTE_NODE", // 2 "TEXT_NODE", // 3 "CDATA_SECTION_NODE", // 4 "ENTITY_REFERENCE_NODE", // 5 "ENTITY_NODE", // 6 "PROCESSING_INSTRUCTION_NODE", // 7 "COMMENT_NODE", // 8 "DOCUMENT_NODE", // 9 "DOCUMENT_TYPE_NODE", // 10 "DOCUMENT_FRAGMENT_NODE", // 11 "NOTATION_NODE" // 12 ]; // ================================================================ // define callback function (ajax) JKL.ParseXML.prototype.async = function ( func, args ) { this.callback_func = func; // callback function this.callback_arg = args; // first argument }; JKL.ParseXML.prototype.onerror = function ( func, args ) { this.onerror_func = func; // callback function }; // ================================================================ // method: parse() // return: parsed object // Download a file from remote server and parse it. JKL.ParseXML.prototype.parse = function () { if ( ! this.http ) return; // set onerror call back if ( this.onerror_func ) { this.http.onerror( this.onerror_func ); } if ( this.callback_func ) { // async mode var copy = this; var proc = function() { if ( ! copy.http ) return; var data = copy.parseResponse(); copy.callback_func( data, copy.callback_arg ); // call back }; this.http.async( proc ); } this.http.load(); if ( ! this.callback_func ) { // sync mode var data = this.parseResponse(); return data; } }; // ================================================================ // every child/children into array JKL.ParseXML.prototype.setOutputArrayAll = function () { this.setOutputArray( true ); } // a child into scalar, children into array JKL.ParseXML.prototype.setOutputArrayAuto = function () { this.setOutputArray( null ); } // every child/children into scalar (first sibiling only) JKL.ParseXML.prototype.setOutputArrayNever = function () { this.setOutputArray( false ); } // specified child/children into array, other child/children into scalar JKL.ParseXML.prototype.setOutputArrayElements = function ( list ) { this.setOutputArray( list ); } // specify how to treate child/children into scalar/array JKL.ParseXML.prototype.setOutputArray = function ( mode ) { if ( typeof(mode) == "string" ) { mode = [ mode ]; // string into array } if ( mode && typeof(mode) == "object" ) { if ( mode.length < 0 ) { mode = false; // false when array == [] } else { var hash = {}; for( var i=0; i" ); // COMMENT_NODE if ( elem.nodeType == 7 ) { return; } // TEXT_NODE CDATA_SECTION_NODE if ( elem.nodeType == 3 || elem.nodeType == 4 ) { // var bool = elem.nodeValue.match( /[^\u0000-\u0020]/ ); var bool = elem.nodeValue.match( /[^\x00-\x20]/ ); // for Safari if ( bool == null ) return; // ignore white spaces // debug.print( "TEXT_NODE: "+elem.nodeValue.length+ " "+bool ); return elem.nodeValue; } var retval; var cnt = {}; // parse attributes if ( elem.attributes && elem.attributes.length ) { retval = {}; for ( var i=0; i -1 ) { if ( text.charAt(nextquote+1) != '"' ) { break; // end of column } nextquote = text.indexOf( '"', nextquote+2 ); } if ( nextquote < 0 ) { // unclosed quote } else if ( text.charAt(nextquote+1) == "," ) { // end of column var quoted = text.substr( pos+1, nextquote-pos-1 ); quoted = quoted.replace(/""/g,'"'); line[line.length] = quoted; pos = nextquote+2; continue; } else if ( text.charAt(nextquote+1) == "\n" || // end of line len==nextquote+1 ) { // end of file var quoted = text.substr( pos+1, nextquote-pos-1 ); quoted = quoted.replace(/""/g,'"'); line[line.length] = quoted; pos = nextquote+2; break; } else { // invalid column } } var nextcomma = text.indexOf( ",", pos ); var nextnline = text.indexOf( "\n", pos ); if ( nextnline < 0 ) nextnline = len; if ( nextcomma > -1 && nextcomma < nextnline ) { line[line.length] = text.substr( pos, nextcomma-pos ); pos = nextcomma+1; } else { // end of line line[line.length] = text.substr( pos, nextnline-pos ); pos = nextnline+1; break; } } if ( line.length >= 0 ) { table[table.length] = line; // push line } } if ( table.length < 0 ) return; // null data return table; }; // ================================================================ // class: JKL.ParseXML.CSVmap JKL.ParseXML.CSVmap = function ( url, query, method ) { // debug.print( "new JKL.ParseXML.CSVmap( '"+url+"', '"+query+"', '"+method+"' );" ); this.http = new JKL.ParseXML.HTTP( url, query, method, true ); return this; }; JKL.ParseXML.CSVmap.prototype.parse = JKL.ParseXML.prototype.parse; JKL.ParseXML.CSVmap.prototype.async = JKL.ParseXML.prototype.async; JKL.ParseXML.CSVmap.prototype.onerror = JKL.ParseXML.prototype.onerror; JKL.ParseXML.CSVmap.prototype.parseCSV = JKL.ParseXML.CSV.prototype.parseCSV; JKL.ParseXML.CSVmap.prototype.parseResponse = function () { var text = this.http.responseText(); var source = this.parseCSV( text ); if ( ! source ) return; if ( source.length < 0 ) return; var title = source.shift(); // first line as title var data = []; for( var i=0; i 0 && this.req.status != 200 && // OK this.req.status != 206 && // Partial Content this.req.status != 304 ) { // Not Modified // debug.print( "status: "+this.req.status ); if ( this.onerror_func ) this.onerror_func( this.req.status ); return false; // failed } return true; // succeed } // ================================================================ // method: documentElement() // return: XML DOM in response body JKL.ParseXML.HTTP.prototype.documentElement = function() { // debug.print( "documentElement: "+this.req ); if ( ! this.req ) return; if ( this.req.responseXML ) { return this.req.responseXML.documentElement; // XMLHTTPRequest } else { return this.req.documentElement; // IXMLDOMDocument } } // ================================================================ // method: responseText() // return: text string in response body JKL.ParseXML.HTTP.prototype.responseText = function() { // debug.print( "responseText: "+this.req ); if ( ! this.req ) return; // Safari and Konqueror cannot understand the encoding of text files. if ( navigator.appVersion.match( "KHTML" ) ) { var esc = escape( this.req.responseText ); // debug.print( "escape: "+esc ); if ( ! esc.match("%u") && esc.match("%") ) { return decodeURIComponent(esc); } } return this.req.responseText; } ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // class: global // function: RemoveNS //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// function RemoveNS(element) { var index = element.indexOf(':'); if (index != -1) return element.substr(index + 1); else return element; } ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // class: global // function: GetXMLElement //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// function GetXMLElement(root, name) { for (var o in root) { var element = RemoveNS(o); if (element.toLowerCase() == name.toLowerCase()) return root[o]; } debugger; return null; } ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // class: global // function: GetXMLChildElement //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// function GetXMLChildElement(root, name) { for (var _o in root) { var obj = root[_o]; return GetXMLElement(obj, name); } debugger; return null; } ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // class: global // function: AddUnique //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// function AddUnique(ar, val) { for (var a=0; a