home *** CD-ROM | disk | FTP | other *** search
/ Practical Internet Web Designer 86 / PIWD86.iso / pc / contents / dreamweaver / software / dwmx2004.exe / Disk1 / data1.cab / Configuration_En / Commands / wddxDes.js < prev   
Encoding:
JavaScript  |  2003-09-05  |  28.4 KB  |  969 lines

  1. // Copyright 2001, 2002, 2003 Macromedia, Inc. All rights reserved.
  2. // WDDX Deserializer for JavaScript
  3. // File: wddxDes.js
  4. // Author: Nate Weiss (nweiss@icesinc.com) 
  5. // Last Updated: 10/1/99
  6. // See www.wddx.org for usage and updates
  7.  
  8. // Update history
  9. // 10/1/99: Added support for <null> and <binary> elements
  10. // 12.11.01: alei - changed the 'length' to 'LENGTH' because 'length' is reserved as an 
  11. //                  array element name for the 'length' of elements in the array
  12. //                  METHODS AFFECTED: wddxDeserializer_parseArray, _attribution
  13.  
  14.  
  15. ///////////////////////////////////////////
  16. // Parses a simple WDDX value            //
  17. // (string, number, dateTime, boolean)   //
  18. // to appropriate Javascript object type //
  19. ///////////////////////////////////////////
  20. function wddxDeserializer_parseSimpleType (Contents) { //hi
  21.  
  22.   // What WDDX-defined simple data type is it?
  23.   var DataType = Contents.name;
  24.  
  25.   // Simple DataType: BOOLEAN
  26.   if (DataType == 'boolean') {
  27.      return (Contents.attributes["value"]=='true');
  28.  
  29.   } else {  
  30.  
  31.     // Value is the value between <string></string> or <number></number>, etc
  32.     var Value = Contents.contents.length > 0 ? Contents.contents[0].value : '';
  33.  
  34.     // Simple DataType: STRING
  35.     if (DataType == 'string') {
  36.         if (Contents.contents.length > 1) {
  37.           Value = '';
  38.           for (StrItem = 0; StrItem < Contents.contents.length; StrItem++) {
  39.             if (Contents.contents[StrItem].type == 'chardata')
  40.               Value = Value + Contents.contents[StrItem].value;
  41.             else if (Contents.contents[StrItem].name == 'char') {
  42.               Code = Contents.contents[StrItem].attributes["code"];
  43.               if      (Code == '0D') Value = Value + '\r';
  44.               else if (Code == '0C') Value = Value + '\f';
  45.               else if (Code == '0A') Value = Value + '\n';
  46.                         else if (Code == '09') Value = Value + '\t';
  47.             }
  48.           }
  49.         }  
  50.         return Value;
  51.     }
  52.  
  53.     // Simple DataType: NUMBER
  54.     else if (DataType == 'number') {
  55.         return parseFloat(Value);
  56.     }
  57.  
  58.     // Simple DataType: NULL  //{nmw 10/1/99}
  59.     else if (DataType == 'null') {
  60.       return null;
  61.     }  
  62.  
  63.     // Simple DataType: DATE
  64.     else if (DataType == 'dateTime') {
  65.         // Split date string into component parts
  66.         var Value = splitAny(Value, 'T');
  67.         var dtDateParts = splitAny(Value[0], '-');
  68.         var NewDate;
  69.         
  70.  
  71.         if ( (Value[1].indexOf('-') == -1) & (Value[1].indexOf('+') == -1) ) {
  72.           // create native JS Date object
  73.           var dtTimeParts = splitAny(Value[1], ':');
  74.           NewDate = new Date(dtDateParts[0], dtDateParts[1]-1, dtDateParts[2], dtTimeParts[0], dtTimeParts[1], dtTimeParts[2]);
  75.           
  76.         } else {  
  77.           
  78.           // There is timezone info for this <dateTime></dateTime> element.
  79.           // Get just the timezone info by getting everything after the "-" or "+"
  80.           if (Value[1].indexOf('-') > -1) dtTimeTZParts = splitAny(Value[1], '-');
  81.             else dtTimeTZParts = splitAny(Value[1], '+');
  82.           var dtTimeParts = splitAny(dtTimeTZParts[0], ':');
  83.  
  84.           // Create a new JS date object (no timezone offsetting has happened yet)
  85.           NewDate = new Date(dtDateParts[0], dtDateParts[1]-1, dtDateParts[2], dtTimeParts[0], dtTimeParts[1], dtTimeParts[2]);
  86.  
  87.           // If we are supposed to do timezone offsetting
  88.           if (this.useTimezoneInfo == true) {
  89.             var dtTZParts = splitAny(dtTimeTZParts[1], ':');
  90.             var dtOffsetHours = parseInt(dtTZParts[0]);
  91.             var dtOffsetMins =  parseInt(dtTZParts[1]);
  92.             if (Value[1].indexOf('-') > -1) {
  93.               dtOffsetHours = this.timezoneOffsetHours - dtOffsetHours;
  94.               dtOffsetMins  = this.timezoneOffsetMinutes - dtOffsetMins;
  95.             } else {
  96.               dtOffsetHours = this.timezoneOffsetHours + dtOffsetHours;
  97.               dtOffsetMins  = this.timezoneOffsetMinutes + dtOffsetMins;
  98.             }
  99.             NewDate.setHours(NewDate.getHours() - dtOffsetHours);
  100.             NewDate.setMinutes(NewDate.getMinutes() - dtOffsetMins);
  101.           }  
  102.           
  103.         }
  104.         return NewDate;
  105.  
  106.     }
  107.   }
  108.   return null;
  109. }
  110.  
  111.  
  112.  
  113. ///////////////////////////////////////////
  114. // Desearializes WXXX Array by creating  //
  115. // JS Array object & populating it with  //
  116. // Deserialized simple values            //
  117. ///////////////////////////////////////////
  118. function wddxDeserializer_parseArray(ArrayAsWDDX) {
  119.   // JSArray is the new Javascript-style array to return
  120.   // ArrayLength is the length of the WDDX-style array to parse
  121.   var JSArray = new Array();
  122.   // Changed from 'length' to 'LENGTH' because setting 'length' as an array element name throws an
  123.   // error in UD vs IE4/NS4/NS6 simply ignoring the error
  124.   // var ArrayLength = parseInt(ArrayAsWDDX.attributes["length"]);
  125.   var ArrayLength = parseInt(ArrayAsWDDX.attributes["LENGTH"]);
  126.   // For each element in the WDDX array, set the corresponding
  127.   // Element in the JS array to the WDDX element's parsed value  
  128.   for (var Count = 0; Count < ArrayLength; Count++) { 
  129.     JSArray[Count] = this.parseElement(ArrayAsWDDX.contents[Count]);
  130.   }
  131.  
  132.   // Return the finished array
  133.   return JSArray;
  134. }
  135.  
  136.  
  137.  
  138. ///////////////////////////////////////////
  139. // Desearializes a Structure by creating //
  140. // JS Array object & populating it with  //
  141. // appropriately Deserialized values     //
  142. ///////////////////////////////////////////
  143. function wddxDeserializer_parseStruct(StructAsWDDX) {
  144.   // The JavaScript object that we're building right now
  145.   var JSObject;
  146.  
  147.   // StructLength is the length of the WDDX-style structure to parse
  148.   var StructLength = StructAsWDDX.contents.length;
  149.  
  150.   // JSObject is the new Javascript-style object to return
  151.   // Call object constructor if a "type" attribute has been provided
  152.   // for this <struct> element; otherwise, call generic Object constructor
  153.   var bCustom = false;
  154.   
  155.   if (typeof(StructAsWDDX.attributes["type"]) == 'string') {
  156.     if(StructAsWDDX.attributes["type"].toLowerCase() != "coldfusion.util.fasthashtable"){
  157.         var ConstructorTest = 'typeof(' +StructAsWDDX.attributes["type"]+ ')';
  158.         if ( eval(ConstructorTest) == 'function' )
  159.           bCustom = true;
  160.     }
  161.   }
  162.  
  163.   if (bCustom) JSObject = eval('new '+ StructAsWDDX.attributes["type"]);
  164.   else         JSObject = new Object;
  165.  
  166.   
  167.   // For each element in the WDDX struct, set the corresponding
  168.   // Element in the JS object to the WDDX element's parsed value.
  169.   // StructIndex is the "name" of the stucture element, ie MyStruct["StuctIndex"]
  170.   for (var Count = 0; Count < StructLength; Count++) { 
  171.     var StructIndex = (this.preserveVarCase == true) ? StructAsWDDX.contents[Count].attributes["name"] : (this.varCaseToUpper == true) ? StructAsWDDX.contents[Count].attributes["name"].toUpperCase() : StructAsWDDX.contents[Count].attributes["name"].toLowerCase(); 
  172.     JSObject[StructIndex] = this.parseElement(StructAsWDDX.contents[Count].contents[0]);
  173.   }
  174.   
  175.  
  176.   // Return the finished object
  177.   return JSObject;
  178. }
  179.  
  180.  
  181.  
  182. ///////////////////////////////////////////
  183. // Desearializes a recordset by creating //
  184. // JS WDDXRecordset object & populating  //
  185. // its cells with Deser'd simple values  //
  186. ///////////////////////////////////////////
  187. function wddxDeserializer_parseRecordset(RSAsWDDX) {
  188.   // RSInfo is the <recordset>...</recordset> part of the WDDX packet
  189.   // RSCols is an array full of column names
  190.   // RSRows is the number of rows in the recordset
  191.   // ThisRS is an actual WddxRecordset object
  192.   var RSInfo = RSAsWDDX;
  193.   var RSColNames = RSInfo.attributes["fieldNames"].toLowerCase();
  194.   var RSCols = splitAny(RSColNames, ',');
  195.   var RSRows = parseInt(RSInfo.attributes["rowCount"]);
  196.   var ThisRS = new WddxRecordset(RSCols, RSRows);  // Note dependency on external wddx.js source file
  197.  
  198.   // For each column in the recordset...
  199.   // ThisCol is the current column name (as a string)
  200.   // ColArray is an array of cells for column (going down in rows)
  201.   for (var ColNo = 0; ColNo < RSCols.length; ColNo++) {
  202.     ThisCol = RSCols[ColNo];
  203.     ColArray = new Array();
  204.  
  205.     // For each row in the column, get value from WDDX packet
  206.     for (var RowNo = 0; RowNo < RSRows; RowNo++) {
  207.       ColArray[RowNo] = this.parseSimpleType(RSInfo.contents[ColNo].contents[RowNo]);
  208.     }
  209.  
  210.     // Attach array of this column's values to recordset itself
  211.     ThisRS[ThisCol] = ColArray;
  212.   }
  213.  
  214.   // Return the recordset object
  215.   return ThisRS;
  216. }
  217.  
  218.  
  219. ///////////////////////////////////////////
  220. // Called by the Deserializer function   //
  221. // Basically decides if this element is  //
  222. // Simple Type or Recordset or Structure //
  223. ///////////////////////////////////////////
  224. function wddxDeserializer_parseElement(Element) {
  225.  
  226.   // WHAT KIND OF ELEMENT IS IT?
  227.     // if it's a recordset
  228.     if (Element.name == 'recordset') {
  229.       return this.parseRecordset(Element);
  230.     }
  231.  
  232.     // if it's an array
  233.     else if (Element.name == 'array') { 
  234.       return this.parseArray(Element);
  235.     }
  236.     
  237.  
  238.     // if it's a structure
  239.     else if (Element.name == 'struct') {
  240.       return this.parseStruct(Element);
  241.     }
  242.       
  243.     // if it's a binary //{nmw 10/1/99}
  244.     else if (Element.name == 'binary') {
  245.       var Bin = new WddxBinary;
  246.       Bin.encoding = (typeof(Element.attributes["encoding"]) == 'string') ? Element.attributes["encoding"] : 'base64';  
  247.       
  248.       if (this.preserveBinaryData) {
  249.         Bin.data = (typeof(Element.contents[0].value) == 'string') ? Element.contents[0].value : '';         
  250.       };
  251.         
  252.       return Bin;
  253.     }  
  254.     
  255.     
  256.     // if it's a simple element (string, number, dateTime, boolean)
  257.     //if ((Element.name == 'boolean' || Element.name == 'null') || (Element.contents.length > 0 && Element.contents[0].type == 'chardata')) 
  258.     else { 
  259.       return this.parseSimpleType(Element);
  260.     };
  261.     
  262.     
  263.   // return nothing if none of supported WDDX types were found
  264.   return '';
  265. }
  266.  
  267.  
  268.  
  269. ////////////////////////////////////////////
  270. // This function will use the native split()
  271. // function if available, and joinOld if not
  272. ////////////////////////////////////////////
  273. function splitAny(String, Sep) {
  274.   if (String.split) SplitArray = String.split(Sep);
  275.   else SplitArray = splitOld(String, Sep);
  276.   
  277.   return SplitArray;
  278. }
  279.  
  280. ////////////////////////////////////////////
  281. // This function will use the native join()
  282. // function if available, and joinOld if not
  283. ////////////////////////////////////////////
  284. function joinAny(theArray, Sep) {
  285.   if (theArray.join) JoinedString = theArray.join(Sep);
  286.   else JoinedString = joinOld(theArray, Sep);
  287.   
  288.   return JoinedString;
  289. }
  290.  
  291.  
  292. //////////////////////////////////////////////////////
  293. // Main public function to deserialize any object   //
  294. //////////////////////////////////////////////////////
  295. function wddxDeserializer_deserialize(WDDXPacket) {
  296.  
  297.   // What's our default var case for struct elements?
  298.   this.varCaseToUpper = (this.defaultVarCase.toLowerCase() != 'lower');
  299.  
  300.   // Set topLevelDatatype property to null by defalt
  301.   this.topLevelDatatype = null;   
  302.  
  303.   // Calculate hours/minutes for this deserializer's timezoneOffset property
  304.   this.timezoneOffsetHours   = Math.round(this.timezoneOffset/60);
  305.   this.timezoneOffsetMinutes = (this.timezoneOffset % 60);
  306.  
  307.   // Use external Xparse XML parser to turn WDDX packet into an object structure
  308.   _Xparse_count = 0;                 // "Resets" the Xparse parser
  309.   var XMLRoot = Xparse(WDDXPacket);  // Returns XML object structure  
  310.   WDDXPacket = '';                   // Discards WDDXPacket variable
  311.   
  312.   // FIND THE WDDX <data>..</data> OBJECT WITHIN JS OBJECT-TREE
  313.   // For each element in the XML-object structure...
  314.   // Examine this "leaf" of the XML-object structure
  315.   // If "leaf" is <data>, then parse its first "child"
  316.   for (var item = 0; item < XMLRoot.index.length; item++) {
  317.     var ThisItem = XMLRoot.index[item];
  318.     if (ThisItem.name == 'data') {
  319.       this.topLevelDatatype = ThisItem.contents[0].name;
  320.     
  321.       // Return result to function
  322.       if (this.parseActualData == true) {
  323.         return this.parseElement(ThisItem.contents[0]);
  324.         break;
  325.       }   
  326.     }
  327.   }
  328.  
  329.   // Return NULL if no data found
  330.   return null;
  331. }
  332.  
  333.  
  334.  
  335. function wddxDeserializer_deserializeUrl(url) {
  336.   var i, pipe, result, packet, posStart, posEnd;
  337.   var tokStart = '<wddxPacket';
  338.   var tokEnd = '</wddxPacket>';
  339.   
  340.   // If URL does not start with "http", 
  341.   // Assume a path based on current folder
  342.   if (url.indexOf('http') != 0) {
  343.     var ThisURL = window.location.href;
  344.     var BaseURL = ThisURL.substring(0, ThisURL.lastIndexOf('/'));
  345.     url = BaseURL + '/' + url;
  346.   }  
  347.  
  348.   for (i = 0; i < document.applets.length; i++) {
  349.  
  350.     if ( (typeof document.applets[i].getClass != 'undefined') && (document.applets[i].getClass() == 'class urlPipe') ) {
  351.       pipe = document.applets[i];
  352.       pipe.catchPage = true;
  353.  
  354.       // add parameters from urlData object-property
  355.       bAdded = false;
  356.       if (typeof(this.urlData) == 'object') {
  357.         for (prop in this.urlData) {
  358.           pipe.addParam( escape(prop.toString()), escape(this.urlData[prop].toString()) );
  359.           bAdded = true;
  360.         };
  361.       };
  362.       // make sure at least one param has been added, or urlPipe may freeze up
  363.       if (bAdded == false) pipe.addParam('dummyParam', 1);
  364.  
  365.       pipe.post( url );  
  366.       packet = new String(pipe.getPage());
  367.       posStart = packet.indexOf(tokStart);
  368.       posEnd = packet.indexOf(tokEnd, posStart);
  369. //alert(packet);     // uncomment this line to view recieved packet
  370.       if (posEnd > posStart) {
  371.         packet = packet.substring( posStart, (posEnd + tokEnd.length) );      
  372.         result = this.deserialize(packet);
  373.       }
  374.       
  375.       // Reset urlData to emtpy
  376.       this.urlData = new Object;
  377.  
  378.       break;
  379.     };
  380.   };
  381.  
  382.   return result;
  383. };
  384.  
  385.  
  386.  
  387.  
  388. function WddxDeserializer() {
  389.   // By default, do not preserve case of "name" 
  390.   // attributes in <var> tags
  391.   this.preserveVarCase = false;
  392.   this.defaultVarCase  = 'upper';
  393.   
  394.   // By default, don't get the DATA from <binary> elements 
  395.   this.preserveBinaryData = true;
  396.   
  397.   // By default, ignore timezone info
  398.   this.useTimezoneInfo = false;
  399.  
  400.   // Use current timezone as default when deserializing  
  401.   // (relevant only if useTimezoneInfo gets set to true)  
  402.   var TempDate = new Date;
  403.   this.timezoneOffset = TempDate.getTimezoneOffset();
  404.   
  405.   // Set topLevelDatatype property to null by defalt
  406.   this.topLevelDatatype = null;
  407.   this.parseActualData  = true;
  408.  
  409.   // urlData should be empty at the outset
  410.   this.urlData = new Object;
  411.  
  412.   // Add the "helper" (private) deserializer functions
  413.   this.parseElement    = wddxDeserializer_parseElement;
  414.   this.parseSimpleType = wddxDeserializer_parseSimpleType;
  415.   this.parseArray      = wddxDeserializer_parseArray;
  416.   this.parseStruct     = wddxDeserializer_parseStruct;
  417.   this.parseRecordset  = wddxDeserializer_parseRecordset;
  418.  
  419.   // Add the main (public) deserializer function
  420.   this.deserialize     = wddxDeserializer_deserialize;
  421.   this.deserializeUrl  = wddxDeserializer_deserializeUrl;
  422.  
  423.   // Set implementation flag      
  424.   this.implementation = 'JS';
  425. }  
  426.  
  427.  
  428. // Provide "standalone" WDDXDeserialize function for backwards 
  429. // compatibility with previous versions of the deserializer.
  430. // This function should be considered "depreciated"  
  431. function WDDXDeserialize(Packet) {
  432.   var Deser = new WddxDeserializer;
  433.   return Deser.deserialize(Packet);
  434. }
  435.  
  436.  
  437.  
  438.  
  439.  
  440.  
  441.  
  442.  
  443.  
  444.  
  445. // ***** The code that follows is known as "Xparse".  It has 
  446. // ***** been slightly modified by Nate Weiss, and included 
  447. // ***** here with permission from Jeremie.  Thanks, Jer! :)   
  448.  
  449.  
  450.  
  451. // Ver .91 Feb 21 1998
  452. //////////////////////////////////////////////////////////////
  453. //
  454. //    Copyright 1998 Jeremie
  455. //    Free for public non-commercial use and modification
  456. //    as long as this header is kept intact and unmodified.
  457. //    Please see http://www.jeremie.com for more information
  458. //    or email jer@jeremie.com with questions/suggestions.
  459. //
  460. ///////////////////////////////////////////////////////////////
  461. ///////////////////////////////////////////////////////////////
  462. ////////// Simple XML Processing Library //////////////////////
  463. ///////////////////////////////////////////////////////////////
  464. ///////////////////////////////////////////////////////////////
  465. ////   Fully complies to the XML 1.0 spec 
  466. ////   as a well-formed processor, with the
  467. ////   exception of full error reporting and
  468. ////   the document type declaration(and it's
  469. ////   related features, internal entities, etc).
  470. ///////////////////////////////////////////////////////////////
  471.  
  472.  
  473. //// ***** This file modified by Nate Weiss 10/98 ****
  474.  
  475.  
  476. /////////////////////////
  477. //// the object constructors for the hybrid DOM
  478.  
  479. function _element()
  480. {
  481.     this.type = "element";
  482.     this.name = new String();
  483.     this.attributes = new Array();
  484.     this.contents = new Array();
  485.     this.uid = _Xparse_count++;
  486.     _Xparse_index[this.uid]=this;
  487. }
  488.  
  489. function _chardata()
  490. {
  491.     this.type = "chardata";
  492.     this.value = new String();
  493. }
  494.  
  495. function _pi()
  496. {
  497.     this.type = "pi";
  498.     this.value = new String();
  499. }
  500.  
  501. function _comment()
  502. {
  503.     this.type = "comment";
  504.     this.value = new String();
  505. }
  506.  
  507. // an internal fragment that is passed between functions
  508. function _frag()
  509. {
  510.     this.str = new String();
  511.     this.ary = new Array();
  512.     this.end = new String();
  513. }
  514.  
  515. /////////////////////////
  516.  
  517.  
  518. // global vars to track element UID's for the index
  519. var _Xparse_count = 0;
  520. var _Xparse_index = new Array();
  521.  
  522. // Global var which is true if the JS1.1 split() and join() functions are supported by the browser
  523. var _Xparse_isSplitSupported = ('Testing'.split && _Xparse_index.join);
  524. var _Xparse_isFromCharCodeSupported = ('Testing'.fromCharCode == 'function');
  525. //var _Xparse_isSplitSupported = false;
  526.  
  527. /////////////////////////
  528. //// Main public function that is called to 
  529. //// parse the XML string and return a root element object
  530.  
  531. function Xparse(src)
  532. {
  533.     var frag = new _frag();
  534.  
  535.     // remove bad \r characters and the prolog
  536.     frag.str = _prolog(src);
  537.  
  538.     // create a root element to contain the document
  539.     var root = new _element();
  540.     root.name="ROOT";
  541.  
  542.     // main recursive function to process the xml
  543.     frag = _compile(frag);
  544.  
  545.     // all done, lets return the root element + index + document
  546.     root.contents = frag.ary;
  547.     root.index = _Xparse_index;
  548.     _Xparse_index = new Array();
  549.     return root;
  550. }
  551.  
  552. /////////////////////////
  553.  
  554.  
  555. /////////////////////////
  556. //// transforms raw text input into a multilevel array
  557. function _compile(frag)
  558. {
  559.     // keep circling and eating the str
  560.     while(1)
  561.     {
  562.         // when the str is empty, return the fragment
  563.         if(frag.str.length == 0)
  564.         {
  565.             return frag;
  566.         }
  567.  
  568.         var TagStart = frag.str.indexOf("<");
  569.  
  570.         if(TagStart != 0)
  571.         {
  572.             // theres a chunk of characters here, store it and go on
  573.             var thisary = frag.ary.length;
  574.             frag.ary[thisary] = new _chardata();
  575.             if(TagStart == -1)
  576.             {
  577.                 frag.ary[thisary].value = _entity(frag.str);
  578.                 frag.str = "";
  579.             }
  580.             else
  581.             {
  582.                 frag.ary[thisary].value = _entity(frag.str.substring(0,TagStart));
  583.                 frag.str = frag.str.substring(TagStart,frag.str.length);
  584.             }
  585.         }
  586.         else
  587.         {
  588.             // determine what the next section is, and process it
  589.             if(frag.str.substring(1,2) == "?")
  590.             {
  591.                 frag = _tag_pi(frag);
  592.             }
  593.             else
  594.             {
  595.                 if(frag.str.substring(1,4) == "!--")
  596.                 {
  597.                     frag = _tag_comment(frag);
  598.                 }
  599.                 else
  600.                 {
  601.                     if(frag.str.substring(1,9) == "![CDATA[")
  602.                     {
  603.                         frag = _tag_cdata(frag);
  604.                     }
  605.                     else
  606.                     {
  607.                         if(frag.str.substring(1,frag.end.length + 3) == "/" + frag.end + ">" || _strip(frag.str.substring(1,frag.end.length + 3)) == "/" + frag.end)
  608.                         {
  609.                             // found the end of the current tag, end the recursive process and return
  610.                             frag.str = frag.str.substring(frag.end.length + 3,frag.str.length);
  611.                             frag.end = "";
  612.                             return frag;
  613.                         }
  614.                         else
  615.                         {
  616.                             frag = _tag_element(frag);
  617.                         }
  618.                     }
  619.                 }
  620.             }
  621.  
  622.         }
  623.     }
  624.     return "";
  625. }
  626. ///////////////////////
  627.  
  628.  
  629. ///////////////////////
  630. //// functions to process different tags
  631.  
  632. function _tag_element(frag)
  633. {
  634.     // initialize some temporary variables for manipulating the tag
  635.     var close = frag.str.indexOf(">");
  636.     var empty = (frag.str.substring(close - 1,close) == "/");
  637.     if(empty)
  638.     {
  639.         close -= 1;
  640.     }
  641.  
  642.     // splitAny up the name and attributes
  643.     var starttag = _normalize(frag.str.substring(1,close));
  644.     var nextspace = starttag.indexOf(" ");
  645.     var attribs = new String();
  646.     var name = new String();
  647.     if(nextspace != -1)
  648.     {
  649.         name = starttag.substring(0,nextspace);
  650.         attribs = starttag.substring(nextspace + 1,starttag.length);
  651.     }
  652.     else
  653.     {
  654.         name = starttag;
  655.     }
  656.  
  657.     var thisary = frag.ary.length;
  658.     frag.ary[thisary] = new _element();
  659.     frag.ary[thisary].name = _strip(name);
  660.     if(attribs.length > 0)
  661.     {
  662.         frag.ary[thisary].attributes = _attribution(attribs);
  663.     }
  664.     if(!empty)
  665.     {
  666.         // !!!! important, 
  667.         // take the contents of the tag and parse them
  668.         var contents = new _frag();
  669.         contents.str = frag.str.substring(close + 1,frag.str.length);
  670.         contents.end = name;
  671.         contents = _compile(contents);
  672.         frag.ary[thisary].contents = contents.ary;
  673.         frag.str = contents.str;
  674.     }
  675.     else
  676.     {
  677.         frag.str = frag.str.substring(close + 2,frag.str.length);
  678.     }
  679.     return frag;
  680. }
  681.  
  682. function _tag_pi(frag)
  683. {
  684.     var close = frag.str.indexOf("?>");
  685.     var val = frag.str.substring(2,close);
  686.     var thisary = frag.ary.length;
  687.     frag.ary[thisary] = new _pi();
  688.     frag.ary[thisary].value = val;
  689.     frag.str = frag.str.substring(close + 2,frag.str.length);
  690.     return frag;
  691. }
  692.  
  693. function _tag_comment(frag)
  694. {
  695.     var close = frag.str.indexOf("-->");
  696.     var val = frag.str.substring(4,close);
  697.     var thisary = frag.ary.length;
  698.     frag.ary[thisary] = new _comment();
  699.     frag.ary[thisary].value = val;
  700.     frag.str = frag.str.substring(close + 3,frag.str.length);
  701.     return frag;
  702. }
  703.  
  704. function _tag_cdata(frag)
  705. {
  706.     var close = frag.str.indexOf("]]>");
  707.     var val = frag.str.substring(9,close);
  708.     var thisary = frag.ary.length;
  709.     frag.ary[thisary] = new _chardata();
  710.     frag.ary[thisary].value = val;
  711.     frag.str = frag.str.substring(close + 3,frag.str.length);
  712.     return frag;
  713. }
  714.  
  715. /////////////////////////
  716.  
  717.  
  718. //////////////////
  719. //// util for element attribute parsing
  720. //// returns an array of all of the keys = values
  721. function _attribution(str)
  722. {
  723.     var all = new Array();
  724.     while(1)
  725.     {
  726.         var eq = str.indexOf("=");
  727.         if(str.length == 0 || eq == -1)
  728.         {
  729.             return all;
  730.         }
  731.  
  732.         var id1 = str.indexOf("\'");
  733.         var id2 = str.indexOf("\"");
  734.         var ids = new Number();
  735.         var id = new String();
  736.         if((id1 < id2 && id1 != -1) || id2 == -1)
  737.         {
  738.             ids = id1;
  739.             id = "\'";
  740.         }
  741.         if((id2 < id1 || id1 == -1) && id2 != -1)
  742.         {
  743.             ids = id2;
  744.             id = "\"";
  745.         }
  746.         var nextid = str.indexOf(id,ids + 1);
  747.         var val = str.substring(ids + 1,nextid);
  748.  
  749.         var name = _strip(str.substring(0,eq));
  750.         // all[name] = _entity(val);
  751.         // 'length' is a reserved element name for JavaScript Arrays
  752.         if( name.toUpperCase() == "LENGTH" ) {
  753.             all['LENGTH'] = _entity(val);
  754.         } else {
  755.             all[name] = _entity(val);
  756.         }
  757.         str = str.substring(nextid + 1,str.length);
  758.     }
  759.     return "";
  760. }
  761. ////////////////////
  762.  
  763.  
  764. //////////////////////
  765. //// util to remove \r characters from input string
  766. //// and return xml string without a prolog
  767. function _prolog(str)
  768. {
  769.     var A = new Array();
  770.  
  771.   if (_Xparse_isSplitSupported) {
  772.       A = str.split("\r\n");
  773.       str = A.join("\n");
  774.       A = str.split("\r");
  775.       str = A.join("\n");
  776.   } else {
  777.       A = splitOld(str, "\r\n");
  778.       str = joinOld(A, "\n");
  779.       A = splitOld(str, "\r");
  780.       str = joinOld(A, "\n");
  781.   }
  782.  
  783.     var start = str.indexOf("<");
  784.     if(str.substring(start,start + 3) == "<?x" || str.substring(start,start + 3) == "<?X" )
  785.     {
  786.         var close = str.indexOf("?>");
  787.         str = str.substring(close + 2,str.length);
  788.     }
  789.     var start = str.indexOf("<!DOCTYPE");
  790.     if(start != -1)
  791.     {
  792.         var close = str.indexOf(">",start) + 1;
  793.         var dp = str.indexOf("[",start);
  794.         if(dp < close && dp != -1)
  795.         {
  796.             close = str.indexOf("]>",start) + 2;
  797.         }
  798.         str = str.substring(close,str.length);
  799.     }
  800.     return str;
  801. }
  802. //////////////////
  803.  
  804.  
  805. //////////////////////
  806. //// util to remove white characters from input string
  807. function _strip(str)
  808. {
  809.     var A = new Array();
  810.  
  811.   if (_Xparse_isSplitSupported) {
  812.       A = str.split("\n");
  813.       str = A.join("");
  814.       A = str.split(" ");
  815.       str = A.join("");
  816.       A = str.split("\t");
  817.       str = A.join("");
  818.   } else {
  819.       A = splitOld(str, "\n");
  820.       str = joinOld(A, "");
  821.       A = splitOld(str, " ");
  822.       str = joinOld(A, "");
  823.       A = splitOld(str, "\t");
  824.       str = joinOld(A, "");
  825.   }
  826.  
  827.     return str;
  828. }
  829. //////////////////
  830.  
  831.  
  832. //////////////////////
  833. //// util to replace white characters in input string
  834. function _normalize(str)
  835. {
  836.     var A = new Array();
  837.  
  838.   if (_Xparse_isSplitSupported) {
  839.       A = str.split("\n");
  840.       str = A.join(" ");
  841.       A = str.split("\t");
  842.       str = A.join(" ");
  843.   } else {
  844.       A = splitOld(str, "\n");
  845.       str = joinOld(A, " ");
  846.       A = splitOld(str, "\t");
  847.       str = joinOld(A, " ");
  848.   }
  849.   
  850.   
  851.     return str;
  852. }
  853. //////////////////
  854.  
  855.  
  856. //////////////////////
  857. //// util to replace internal entities in input string
  858. function _entity(str)
  859. {
  860.     var A = new Array();
  861.  
  862.     
  863.   if (_Xparse_isSplitSupported) {
  864.       A = str.split("<");
  865.       str = A.join("<");
  866.       A = str.split(">");
  867.       str = A.join(">");
  868.       A = str.split(""");
  869.       str = A.join("\"");
  870.       A = str.split("'");
  871.       str = A.join("\'");
  872.       A = str.split("&");
  873.       str = A.join("&");
  874.  
  875.     // Handle accented characters, etc
  876.     while (str.indexOf('&#') > -1) {
  877.       var pos1 = str.indexOf('&#');
  878.       var pos2 = str.indexOf(';', pos1);
  879.       var ent = str.substring(pos1, pos2+1);
  880.       var charNum = parseInt('0' + ent.substring(2));
  881.       
  882.       if (charNum.valueOf() > 0) {
  883.         if (_Xparse_isFromCharCodeSupported) 
  884.           thisChar = String.fromCharCode(charNum);
  885.         else 
  886.           thisChar = '                                  !"#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~ÄÅÇÉÑÖÜáàâäãåçéèêëíìîïñóòôöõúùûü†°¢£§•¶ß®©™´¨≠ÆØ∞±≤≥¥µ∂∑∏π∫ªºΩæø¿¡¬√ƒ≈Δ«»… ÀÃÕŒœ–—“”‘’÷◊ÿŸ⁄€‹›fifl‡·‚„‰ÂÊÁËÈÍÎÏÌÓÔÒÚÛÙıˆ˜¯˘˙˚¸˝˛ˇ'.charAt(charNum);
  887.       };
  888.       
  889.       A = str.split(ent);
  890.       str = A.join(thisChar);
  891.     }
  892.  
  893.   } else {
  894.       A = splitOld(str, "<");
  895.       str = joinOld(A, "<");
  896.       A = splitOld(str, ">");
  897.       str = joinOld(A, ">");
  898.       A = splitOld(str, """);
  899.       str = joinOld(A, "\"");
  900.       A = splitOld(str, "'");
  901.       str = joinOld(A, "\'");
  902.       A = splitOld(str, "&");
  903.       str = joinOld(A, "&");
  904.     
  905.     // Handle accented characters, etc
  906.     while (str.indexOf('&#') > -1) {
  907.       var pos1 = str.indexOf('&#');
  908.       var pos2 = str.indexOf(';', pos1);
  909.       var ent = str.substring(pos1, pos2+1);
  910.       var charNum = parseInt('0' + ent.substring(2));
  911.  
  912.       if (charNum.valueOf() > 0) {
  913.         if (_Xparse_isFromCharCodeSupported) 
  914.           thisChar = String.fromCharCode(charNum);
  915.         else 
  916.           thisChar = '                                  !"#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~ÄÅÇÉÑÖÜáàâäãåçéèêëíìîïñóòôöõúùûü†°¢£§•¶ß®©™´¨≠ÆØ∞±≤≥¥µ∂∑∏π∫ªºΩæø¿¡¬√ƒ≈Δ«»… ÀÃÕŒœ–—“”‘’÷◊ÿŸ⁄€‹›fifl‡·‚„‰ÂÊÁËÈÍÎÏÌÓÔÒÚÛÙıˆ˜¯˘˙˚¸˝˛ˇ'.charAt(charNum);
  917.       };
  918.       
  919.       A = splitOld(str, ent);
  920.       str = joinOld(str, thisChar);
  921.     }    
  922.   }
  923.   
  924.     return str;
  925. }
  926. //////////////////
  927.  
  928.  
  929. //////////////////////////////////////////////
  930. // This function emulates the behavior of
  931. // the Javascript 1.1 string.split() function
  932. //////////////////////////////////////////////
  933. function splitOld(String, Sep) {
  934.   var NewArray = new Array;
  935.   var Chunk = String;
  936.   Sep = Sep.substring(0, 1);
  937.   
  938.   while (Chunk.indexOf(Sep) > -1) {
  939.     NextSep = Chunk.indexOf(Sep);
  940.     NewArray[NewArray.length] = Chunk.substring(0, NextSep);
  941.     Chunk = Chunk.substring(NextSep+1);
  942.   }
  943.  
  944.   NewArray[NewArray.length] = Chunk;  
  945.   return NewArray;
  946. }
  947.  
  948.  
  949. ////////////////////////////////////////////
  950. // This function emulates the behavior of
  951. // the Javascript 1.1 array.join() function
  952. ////////////////////////////////////////////
  953. function joinOld(theArray, Sep) {
  954.   Sep = Sep.substring(0, 1);
  955.   
  956.   if (theArray.length == 0) 
  957.     NewString = '';
  958.   else 
  959.     NewString = theArray[0];
  960.   
  961.   for (var i = 1; i < theArray.length; i++) {
  962.     NewString = NewString + Sep + theArray[i];
  963.   }
  964.   
  965.   return NewString;
  966. }
  967.  
  968.  
  969.