home *** CD-ROM | disk | FTP | other *** search
/ Chip 2002 July / 07_02.iso / software / mdmx / files / DreamweaverMXInstaller.exe / Disk1 / data1.cab / Configuration_En / Commands / wddxDes.js < prev    next >
Encoding:
JavaScript  |  2002-05-01  |  28.3 KB  |  967 lines

  1. // Copyright 2001 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.     var ConstructorTest = 'typeof(' +StructAsWDDX.attributes["type"]+ ')';
  157.     if ( eval(ConstructorTest) == 'function' )
  158.       bCustom = true;
  159.   }
  160.  
  161.   if (bCustom) JSObject = eval('new '+ StructAsWDDX.attributes["type"]);
  162.   else         JSObject = new Object;
  163.  
  164.   
  165.   // For each element in the WDDX struct, set the corresponding
  166.   // Element in the JS object to the WDDX element's parsed value.
  167.   // StructIndex is the "name" of the stucture element, ie MyStruct["StuctIndex"]
  168.   for (var Count = 0; Count < StructLength; Count++) { 
  169.     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(); 
  170.     JSObject[StructIndex] = this.parseElement(StructAsWDDX.contents[Count].contents[0]);
  171.   }
  172.   
  173.  
  174.   // Return the finished object
  175.   return JSObject;
  176. }
  177.  
  178.  
  179.  
  180. ///////////////////////////////////////////
  181. // Desearializes a recordset by creating //
  182. // JS WDDXRecordset object & populating  //
  183. // its cells with Deser'd simple values  //
  184. ///////////////////////////////////////////
  185. function wddxDeserializer_parseRecordset(RSAsWDDX) {
  186.   // RSInfo is the <recordset>...</recordset> part of the WDDX packet
  187.   // RSCols is an array full of column names
  188.   // RSRows is the number of rows in the recordset
  189.   // ThisRS is an actual WddxRecordset object
  190.   var RSInfo = RSAsWDDX;
  191.   var RSColNames = RSInfo.attributes["fieldNames"].toLowerCase();
  192.   var RSCols = splitAny(RSColNames, ',');
  193.   var RSRows = parseInt(RSInfo.attributes["rowCount"]);
  194.   var ThisRS = new WddxRecordset(RSCols, RSRows);  // Note dependency on external wddx.js source file
  195.  
  196.   // For each column in the recordset...
  197.   // ThisCol is the current column name (as a string)
  198.   // ColArray is an array of cells for column (going down in rows)
  199.   for (var ColNo = 0; ColNo < RSCols.length; ColNo++) {
  200.     ThisCol = RSCols[ColNo];
  201.     ColArray = new Array();
  202.  
  203.     // For each row in the column, get value from WDDX packet
  204.     for (var RowNo = 0; RowNo < RSRows; RowNo++) {
  205.       ColArray[RowNo] = this.parseSimpleType(RSInfo.contents[ColNo].contents[RowNo]);
  206.     }
  207.  
  208.     // Attach array of this column's values to recordset itself
  209.     ThisRS[ThisCol] = ColArray;
  210.   }
  211.  
  212.   // Return the recordset object
  213.   return ThisRS;
  214. }
  215.  
  216.  
  217. ///////////////////////////////////////////
  218. // Called by the Deserializer function   //
  219. // Basically decides if this element is  //
  220. // Simple Type or Recordset or Structure //
  221. ///////////////////////////////////////////
  222. function wddxDeserializer_parseElement(Element) {
  223.  
  224.   // WHAT KIND OF ELEMENT IS IT?
  225.     // if it's a recordset
  226.     if (Element.name == 'recordset') {
  227.       return this.parseRecordset(Element);
  228.     }
  229.  
  230.     // if it's an array
  231.     else if (Element.name == 'array') { 
  232.       return this.parseArray(Element);
  233.     }
  234.     
  235.  
  236.     // if it's a structure
  237.     else if (Element.name == 'struct') {
  238.       return this.parseStruct(Element);
  239.     }
  240.       
  241.     // if it's a binary //{nmw 10/1/99}
  242.     else if (Element.name == 'binary') {
  243.       var Bin = new WddxBinary;
  244.       Bin.encoding = (typeof(Element.attributes["encoding"]) == 'string') ? Element.attributes["encoding"] : 'base64';  
  245.       
  246.       if (this.preserveBinaryData) {
  247.         Bin.data = (typeof(Element.contents[0].value) == 'string') ? Element.contents[0].value : '';         
  248.       };
  249.         
  250.       return Bin;
  251.     }  
  252.     
  253.     
  254.     // if it's a simple element (string, number, dateTime, boolean)
  255.     //if ((Element.name == 'boolean' || Element.name == 'null') || (Element.contents.length > 0 && Element.contents[0].type == 'chardata')) 
  256.     else { 
  257.       return this.parseSimpleType(Element);
  258.     };
  259.     
  260.     
  261.   // return nothing if none of supported WDDX types were found
  262.   return '';
  263. }
  264.  
  265.  
  266.  
  267. ////////////////////////////////////////////
  268. // This function will use the native split()
  269. // function if available, and joinOld if not
  270. ////////////////////////////////////////////
  271. function splitAny(String, Sep) {
  272.   if (String.split) SplitArray = String.split(Sep);
  273.   else SplitArray = splitOld(String, Sep);
  274.   
  275.   return SplitArray;
  276. }
  277.  
  278. ////////////////////////////////////////////
  279. // This function will use the native join()
  280. // function if available, and joinOld if not
  281. ////////////////////////////////////////////
  282. function joinAny(theArray, Sep) {
  283.   if (theArray.join) JoinedString = theArray.join(Sep);
  284.   else JoinedString = joinOld(theArray, Sep);
  285.   
  286.   return JoinedString;
  287. }
  288.  
  289.  
  290. //////////////////////////////////////////////////////
  291. // Main public function to deserialize any object   //
  292. //////////////////////////////////////////////////////
  293. function wddxDeserializer_deserialize(WDDXPacket) {
  294.  
  295.   // What's our default var case for struct elements?
  296.   this.varCaseToUpper = (this.defaultVarCase.toLowerCase() != 'lower');
  297.  
  298.   // Set topLevelDatatype property to null by defalt
  299.   this.topLevelDatatype = null;   
  300.  
  301.   // Calculate hours/minutes for this deserializer's timezoneOffset property
  302.   this.timezoneOffsetHours   = Math.round(this.timezoneOffset/60);
  303.   this.timezoneOffsetMinutes = (this.timezoneOffset % 60);
  304.  
  305.   // Use external Xparse XML parser to turn WDDX packet into an object structure
  306.   _Xparse_count = 0;                 // "Resets" the Xparse parser
  307.   var XMLRoot = Xparse(WDDXPacket);  // Returns XML object structure  
  308.   WDDXPacket = '';                   // Discards WDDXPacket variable
  309.   
  310.   // FIND THE WDDX <data>..</data> OBJECT WITHIN JS OBJECT-TREE
  311.   // For each element in the XML-object structure...
  312.   // Examine this "leaf" of the XML-object structure
  313.   // If "leaf" is <data>, then parse its first "child"
  314.   for (var item = 0; item < XMLRoot.index.length; item++) {
  315.     var ThisItem = XMLRoot.index[item];
  316.     if (ThisItem.name == 'data') {
  317.       this.topLevelDatatype = ThisItem.contents[0].name;
  318.     
  319.       // Return result to function
  320.       if (this.parseActualData == true) {
  321.         return this.parseElement(ThisItem.contents[0]);
  322.         break;
  323.       }   
  324.     }
  325.   }
  326.  
  327.   // Return NULL if no data found
  328.   return null;
  329. }
  330.  
  331.  
  332.  
  333. function wddxDeserializer_deserializeUrl(url) {
  334.   var i, pipe, result, packet, posStart, posEnd;
  335.   var tokStart = '<wddxPacket';
  336.   var tokEnd = '</wddxPacket>';
  337.   
  338.   // If URL does not start with "http", 
  339.   // Assume a path based on current folder
  340.   if (url.indexOf('http') != 0) {
  341.     var ThisURL = window.location.href;
  342.     var BaseURL = ThisURL.substring(0, ThisURL.lastIndexOf('/'));
  343.     url = BaseURL + '/' + url;
  344.   }  
  345.  
  346.   for (i = 0; i < document.applets.length; i++) {
  347.  
  348.     if ( (typeof document.applets[i].getClass != 'undefined') && (document.applets[i].getClass() == 'class urlPipe') ) {
  349.       pipe = document.applets[i];
  350.       pipe.catchPage = true;
  351.  
  352.       // add parameters from urlData object-property
  353.       bAdded = false;
  354.       if (typeof(this.urlData) == 'object') {
  355.         for (prop in this.urlData) {
  356.           pipe.addParam( escape(prop.toString()), escape(this.urlData[prop].toString()) );
  357.           bAdded = true;
  358.         };
  359.       };
  360.       // make sure at least one param has been added, or urlPipe may freeze up
  361.       if (bAdded == false) pipe.addParam('dummyParam', 1);
  362.  
  363.       pipe.post( url );  
  364.       packet = new String(pipe.getPage());
  365.       posStart = packet.indexOf(tokStart);
  366.       posEnd = packet.indexOf(tokEnd, posStart);
  367. //alert(packet);     // uncomment this line to view recieved packet
  368.       if (posEnd > posStart) {
  369.         packet = packet.substring( posStart, (posEnd + tokEnd.length) );      
  370.         result = this.deserialize(packet);
  371.       }
  372.       
  373.       // Reset urlData to emtpy
  374.       this.urlData = new Object;
  375.  
  376.       break;
  377.     };
  378.   };
  379.  
  380.   return result;
  381. };
  382.  
  383.  
  384.  
  385.  
  386. function WddxDeserializer() {
  387.   // By default, do not preserve case of "name" 
  388.   // attributes in <var> tags
  389.   this.preserveVarCase = false;
  390.   this.defaultVarCase  = 'upper';
  391.   
  392.   // By default, don't get the DATA from <binary> elements 
  393.   this.preserveBinaryData = true;
  394.   
  395.   // By default, ignore timezone info
  396.   this.useTimezoneInfo = false;
  397.  
  398.   // Use current timezone as default when deserializing  
  399.   // (relevant only if useTimezoneInfo gets set to true)  
  400.   var TempDate = new Date;
  401.   this.timezoneOffset = TempDate.getTimezoneOffset();
  402.   
  403.   // Set topLevelDatatype property to null by defalt
  404.   this.topLevelDatatype = null;
  405.   this.parseActualData  = true;
  406.  
  407.   // urlData should be empty at the outset
  408.   this.urlData = new Object;
  409.  
  410.   // Add the "helper" (private) deserializer functions
  411.   this.parseElement    = wddxDeserializer_parseElement;
  412.   this.parseSimpleType = wddxDeserializer_parseSimpleType;
  413.   this.parseArray      = wddxDeserializer_parseArray;
  414.   this.parseStruct     = wddxDeserializer_parseStruct;
  415.   this.parseRecordset  = wddxDeserializer_parseRecordset;
  416.  
  417.   // Add the main (public) deserializer function
  418.   this.deserialize     = wddxDeserializer_deserialize;
  419.   this.deserializeUrl  = wddxDeserializer_deserializeUrl;
  420.  
  421.   // Set implementation flag      
  422.   this.implementation = 'JS';
  423. }  
  424.  
  425.  
  426. // Provide "standalone" WDDXDeserialize function for backwards 
  427. // compatibility with previous versions of the deserializer.
  428. // This function should be considered "depreciated"  
  429. function WDDXDeserialize(Packet) {
  430.   var Deser = new WddxDeserializer;
  431.   return Deser.deserialize(Packet);
  432. }
  433.  
  434.  
  435.  
  436.  
  437.  
  438.  
  439.  
  440.  
  441.  
  442.  
  443. // ***** The code that follows is known as "Xparse".  It has 
  444. // ***** been slightly modified by Nate Weiss, and included 
  445. // ***** here with permission from Jeremie.  Thanks, Jer! :)   
  446.  
  447.  
  448.  
  449. // Ver .91 Feb 21 1998
  450. //////////////////////////////////////////////////////////////
  451. //
  452. //    Copyright 1998 Jeremie
  453. //    Free for public non-commercial use and modification
  454. //    as long as this header is kept intact and unmodified.
  455. //    Please see http://www.jeremie.com for more information
  456. //    or email jer@jeremie.com with questions/suggestions.
  457. //
  458. ///////////////////////////////////////////////////////////////
  459. ///////////////////////////////////////////////////////////////
  460. ////////// Simple XML Processing Library //////////////////////
  461. ///////////////////////////////////////////////////////////////
  462. ///////////////////////////////////////////////////////////////
  463. ////   Fully complies to the XML 1.0 spec 
  464. ////   as a well-formed processor, with the
  465. ////   exception of full error reporting and
  466. ////   the document type declaration(and it's
  467. ////   related features, internal entities, etc).
  468. ///////////////////////////////////////////////////////////////
  469.  
  470.  
  471. //// ***** This file modified by Nate Weiss 10/98 ****
  472.  
  473.  
  474. /////////////////////////
  475. //// the object constructors for the hybrid DOM
  476.  
  477. function _element()
  478. {
  479.     this.type = "element";
  480.     this.name = new String();
  481.     this.attributes = new Array();
  482.     this.contents = new Array();
  483.     this.uid = _Xparse_count++;
  484.     _Xparse_index[this.uid]=this;
  485. }
  486.  
  487. function _chardata()
  488. {
  489.     this.type = "chardata";
  490.     this.value = new String();
  491. }
  492.  
  493. function _pi()
  494. {
  495.     this.type = "pi";
  496.     this.value = new String();
  497. }
  498.  
  499. function _comment()
  500. {
  501.     this.type = "comment";
  502.     this.value = new String();
  503. }
  504.  
  505. // an internal fragment that is passed between functions
  506. function _frag()
  507. {
  508.     this.str = new String();
  509.     this.ary = new Array();
  510.     this.end = new String();
  511. }
  512.  
  513. /////////////////////////
  514.  
  515.  
  516. // global vars to track element UID's for the index
  517. var _Xparse_count = 0;
  518. var _Xparse_index = new Array();
  519.  
  520. // Global var which is true if the JS1.1 split() and join() functions are supported by the browser
  521. var _Xparse_isSplitSupported = ('Testing'.split && _Xparse_index.join);
  522. var _Xparse_isFromCharCodeSupported = ('Testing'.fromCharCode == 'function');
  523. //var _Xparse_isSplitSupported = false;
  524.  
  525. /////////////////////////
  526. //// Main public function that is called to 
  527. //// parse the XML string and return a root element object
  528.  
  529. function Xparse(src)
  530. {
  531.     var frag = new _frag();
  532.  
  533.     // remove bad \r characters and the prolog
  534.     frag.str = _prolog(src);
  535.  
  536.     // create a root element to contain the document
  537.     var root = new _element();
  538.     root.name="ROOT";
  539.  
  540.     // main recursive function to process the xml
  541.     frag = _compile(frag);
  542.  
  543.     // all done, lets return the root element + index + document
  544.     root.contents = frag.ary;
  545.     root.index = _Xparse_index;
  546.     _Xparse_index = new Array();
  547.     return root;
  548. }
  549.  
  550. /////////////////////////
  551.  
  552.  
  553. /////////////////////////
  554. //// transforms raw text input into a multilevel array
  555. function _compile(frag)
  556. {
  557.     // keep circling and eating the str
  558.     while(1)
  559.     {
  560.         // when the str is empty, return the fragment
  561.         if(frag.str.length == 0)
  562.         {
  563.             return frag;
  564.         }
  565.  
  566.         var TagStart = frag.str.indexOf("<");
  567.  
  568.         if(TagStart != 0)
  569.         {
  570.             // theres a chunk of characters here, store it and go on
  571.             var thisary = frag.ary.length;
  572.             frag.ary[thisary] = new _chardata();
  573.             if(TagStart == -1)
  574.             {
  575.                 frag.ary[thisary].value = _entity(frag.str);
  576.                 frag.str = "";
  577.             }
  578.             else
  579.             {
  580.                 frag.ary[thisary].value = _entity(frag.str.substring(0,TagStart));
  581.                 frag.str = frag.str.substring(TagStart,frag.str.length);
  582.             }
  583.         }
  584.         else
  585.         {
  586.             // determine what the next section is, and process it
  587.             if(frag.str.substring(1,2) == "?")
  588.             {
  589.                 frag = _tag_pi(frag);
  590.             }
  591.             else
  592.             {
  593.                 if(frag.str.substring(1,4) == "!--")
  594.                 {
  595.                     frag = _tag_comment(frag);
  596.                 }
  597.                 else
  598.                 {
  599.                     if(frag.str.substring(1,9) == "![CDATA[")
  600.                     {
  601.                         frag = _tag_cdata(frag);
  602.                     }
  603.                     else
  604.                     {
  605.                         if(frag.str.substring(1,frag.end.length + 3) == "/" + frag.end + ">" || _strip(frag.str.substring(1,frag.end.length + 3)) == "/" + frag.end)
  606.                         {
  607.                             // found the end of the current tag, end the recursive process and return
  608.                             frag.str = frag.str.substring(frag.end.length + 3,frag.str.length);
  609.                             frag.end = "";
  610.                             return frag;
  611.                         }
  612.                         else
  613.                         {
  614.                             frag = _tag_element(frag);
  615.                         }
  616.                     }
  617.                 }
  618.             }
  619.  
  620.         }
  621.     }
  622.     return "";
  623. }
  624. ///////////////////////
  625.  
  626.  
  627. ///////////////////////
  628. //// functions to process different tags
  629.  
  630. function _tag_element(frag)
  631. {
  632.     // initialize some temporary variables for manipulating the tag
  633.     var close = frag.str.indexOf(">");
  634.     var empty = (frag.str.substring(close - 1,close) == "/");
  635.     if(empty)
  636.     {
  637.         close -= 1;
  638.     }
  639.  
  640.     // splitAny up the name and attributes
  641.     var starttag = _normalize(frag.str.substring(1,close));
  642.     var nextspace = starttag.indexOf(" ");
  643.     var attribs = new String();
  644.     var name = new String();
  645.     if(nextspace != -1)
  646.     {
  647.         name = starttag.substring(0,nextspace);
  648.         attribs = starttag.substring(nextspace + 1,starttag.length);
  649.     }
  650.     else
  651.     {
  652.         name = starttag;
  653.     }
  654.  
  655.     var thisary = frag.ary.length;
  656.     frag.ary[thisary] = new _element();
  657.     frag.ary[thisary].name = _strip(name);
  658.     if(attribs.length > 0)
  659.     {
  660.         frag.ary[thisary].attributes = _attribution(attribs);
  661.     }
  662.     if(!empty)
  663.     {
  664.         // !!!! important, 
  665.         // take the contents of the tag and parse them
  666.         var contents = new _frag();
  667.         contents.str = frag.str.substring(close + 1,frag.str.length);
  668.         contents.end = name;
  669.         contents = _compile(contents);
  670.         frag.ary[thisary].contents = contents.ary;
  671.         frag.str = contents.str;
  672.     }
  673.     else
  674.     {
  675.         frag.str = frag.str.substring(close + 2,frag.str.length);
  676.     }
  677.     return frag;
  678. }
  679.  
  680. function _tag_pi(frag)
  681. {
  682.     var close = frag.str.indexOf("?>");
  683.     var val = frag.str.substring(2,close);
  684.     var thisary = frag.ary.length;
  685.     frag.ary[thisary] = new _pi();
  686.     frag.ary[thisary].value = val;
  687.     frag.str = frag.str.substring(close + 2,frag.str.length);
  688.     return frag;
  689. }
  690.  
  691. function _tag_comment(frag)
  692. {
  693.     var close = frag.str.indexOf("-->");
  694.     var val = frag.str.substring(4,close);
  695.     var thisary = frag.ary.length;
  696.     frag.ary[thisary] = new _comment();
  697.     frag.ary[thisary].value = val;
  698.     frag.str = frag.str.substring(close + 3,frag.str.length);
  699.     return frag;
  700. }
  701.  
  702. function _tag_cdata(frag)
  703. {
  704.     var close = frag.str.indexOf("]]>");
  705.     var val = frag.str.substring(9,close);
  706.     var thisary = frag.ary.length;
  707.     frag.ary[thisary] = new _chardata();
  708.     frag.ary[thisary].value = val;
  709.     frag.str = frag.str.substring(close + 3,frag.str.length);
  710.     return frag;
  711. }
  712.  
  713. /////////////////////////
  714.  
  715.  
  716. //////////////////
  717. //// util for element attribute parsing
  718. //// returns an array of all of the keys = values
  719. function _attribution(str)
  720. {
  721.     var all = new Array();
  722.     while(1)
  723.     {
  724.         var eq = str.indexOf("=");
  725.         if(str.length == 0 || eq == -1)
  726.         {
  727.             return all;
  728.         }
  729.  
  730.         var id1 = str.indexOf("\'");
  731.         var id2 = str.indexOf("\"");
  732.         var ids = new Number();
  733.         var id = new String();
  734.         if((id1 < id2 && id1 != -1) || id2 == -1)
  735.         {
  736.             ids = id1;
  737.             id = "\'";
  738.         }
  739.         if((id2 < id1 || id1 == -1) && id2 != -1)
  740.         {
  741.             ids = id2;
  742.             id = "\"";
  743.         }
  744.         var nextid = str.indexOf(id,ids + 1);
  745.         var val = str.substring(ids + 1,nextid);
  746.  
  747.         var name = _strip(str.substring(0,eq));
  748.         // all[name] = _entity(val);
  749.         // 'length' is a reserved element name for JavaScript Arrays
  750.         if( name.toUpperCase() == "LENGTH" ) {
  751.             all['LENGTH'] = _entity(val);
  752.         } else {
  753.             all[name] = _entity(val);
  754.         }
  755.         str = str.substring(nextid + 1,str.length);
  756.     }
  757.     return "";
  758. }
  759. ////////////////////
  760.  
  761.  
  762. //////////////////////
  763. //// util to remove \r characters from input string
  764. //// and return xml string without a prolog
  765. function _prolog(str)
  766. {
  767.     var A = new Array();
  768.  
  769.   if (_Xparse_isSplitSupported) {
  770.       A = str.split("\r\n");
  771.       str = A.join("\n");
  772.       A = str.split("\r");
  773.       str = A.join("\n");
  774.   } else {
  775.       A = splitOld(str, "\r\n");
  776.       str = joinOld(A, "\n");
  777.       A = splitOld(str, "\r");
  778.       str = joinOld(A, "\n");
  779.   }
  780.  
  781.     var start = str.indexOf("<");
  782.     if(str.substring(start,start + 3) == "<?x" || str.substring(start,start + 3) == "<?X" )
  783.     {
  784.         var close = str.indexOf("?>");
  785.         str = str.substring(close + 2,str.length);
  786.     }
  787.     var start = str.indexOf("<!DOCTYPE");
  788.     if(start != -1)
  789.     {
  790.         var close = str.indexOf(">",start) + 1;
  791.         var dp = str.indexOf("[",start);
  792.         if(dp < close && dp != -1)
  793.         {
  794.             close = str.indexOf("]>",start) + 2;
  795.         }
  796.         str = str.substring(close,str.length);
  797.     }
  798.     return str;
  799. }
  800. //////////////////
  801.  
  802.  
  803. //////////////////////
  804. //// util to remove white characters from input string
  805. function _strip(str)
  806. {
  807.     var A = new Array();
  808.  
  809.   if (_Xparse_isSplitSupported) {
  810.       A = str.split("\n");
  811.       str = A.join("");
  812.       A = str.split(" ");
  813.       str = A.join("");
  814.       A = str.split("\t");
  815.       str = A.join("");
  816.   } else {
  817.       A = splitOld(str, "\n");
  818.       str = joinOld(A, "");
  819.       A = splitOld(str, " ");
  820.       str = joinOld(A, "");
  821.       A = splitOld(str, "\t");
  822.       str = joinOld(A, "");
  823.   }
  824.  
  825.     return str;
  826. }
  827. //////////////////
  828.  
  829.  
  830. //////////////////////
  831. //// util to replace white characters in input string
  832. function _normalize(str)
  833. {
  834.     var A = new Array();
  835.  
  836.   if (_Xparse_isSplitSupported) {
  837.       A = str.split("\n");
  838.       str = A.join(" ");
  839.       A = str.split("\t");
  840.       str = A.join(" ");
  841.   } else {
  842.       A = splitOld(str, "\n");
  843.       str = joinOld(A, " ");
  844.       A = splitOld(str, "\t");
  845.       str = joinOld(A, " ");
  846.   }
  847.   
  848.   
  849.     return str;
  850. }
  851. //////////////////
  852.  
  853.  
  854. //////////////////////
  855. //// util to replace internal entities in input string
  856. function _entity(str)
  857. {
  858.     var A = new Array();
  859.  
  860.     
  861.   if (_Xparse_isSplitSupported) {
  862.       A = str.split("<");
  863.       str = A.join("<");
  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.  
  873.     // Handle accented characters, etc
  874.     while (str.indexOf('&#') > -1) {
  875.       var pos1 = str.indexOf('&#');
  876.       var pos2 = str.indexOf(';', pos1);
  877.       var ent = str.substring(pos1, pos2+1);
  878.       var charNum = parseInt('0' + ent.substring(2));
  879.       
  880.       if (charNum.valueOf() > 0) {
  881.         if (_Xparse_isFromCharCodeSupported) 
  882.           thisChar = String.fromCharCode(charNum);
  883.         else 
  884.           thisChar = '                                  !"#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~ÇüéâäàåçêëèïîìÄÅÉæÆôöòûùÿÖÜ¢£¥₧ƒáíóúñѪº¿⌐¬½¼¡«»░▒▓│┤╡╢╖╕╣║╗╝╜╛┐└┴┬├─┼╞╟╚╔╩╦╠═╬╧╨╤╥╙╘╒╓╫╪┘┌█▄▌▐▀αßΓπΣσµτΦΘΩδ∞φε∩≡±≥≤⌠⌡÷≈°∙·√ⁿ²■ '.charAt(charNum);
  885.       };
  886.       
  887.       A = str.split(ent);
  888.       str = A.join(thisChar);
  889.     }
  890.  
  891.   } else {
  892.       A = splitOld(str, "<");
  893.       str = joinOld(A, "<");
  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.     
  903.     // Handle accented characters, etc
  904.     while (str.indexOf('&#') > -1) {
  905.       var pos1 = str.indexOf('&#');
  906.       var pos2 = str.indexOf(';', pos1);
  907.       var ent = str.substring(pos1, pos2+1);
  908.       var charNum = parseInt('0' + ent.substring(2));
  909.  
  910.       if (charNum.valueOf() > 0) {
  911.         if (_Xparse_isFromCharCodeSupported) 
  912.           thisChar = String.fromCharCode(charNum);
  913.         else 
  914.           thisChar = '                                  !"#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~ÇüéâäàåçêëèïîìÄÅÉæÆôöòûùÿÖÜ¢£¥₧ƒáíóúñѪº¿⌐¬½¼¡«»░▒▓│┤╡╢╖╕╣║╗╝╜╛┐└┴┬├─┼╞╟╚╔╩╦╠═╬╧╨╤╥╙╘╒╓╫╪┘┌█▄▌▐▀αßΓπΣσµτΦΘΩδ∞φε∩≡±≥≤⌠⌡÷≈°∙·√ⁿ²■ '.charAt(charNum);
  915.       };
  916.       
  917.       A = splitOld(str, ent);
  918.       str = joinOld(str, thisChar);
  919.     }    
  920.   }
  921.   
  922.     return str;
  923. }
  924. //////////////////
  925.  
  926.  
  927. //////////////////////////////////////////////
  928. // This function emulates the behavior of
  929. // the Javascript 1.1 string.split() function
  930. //////////////////////////////////////////////
  931. function splitOld(String, Sep) {
  932.   var NewArray = new Array;
  933.   var Chunk = String;
  934.   Sep = Sep.substring(0, 1);
  935.   
  936.   while (Chunk.indexOf(Sep) > -1) {
  937.     NextSep = Chunk.indexOf(Sep);
  938.     NewArray[NewArray.length] = Chunk.substring(0, NextSep);
  939.     Chunk = Chunk.substring(NextSep+1);
  940.   }
  941.  
  942.   NewArray[NewArray.length] = Chunk;  
  943.   return NewArray;
  944. }
  945.  
  946.  
  947. ////////////////////////////////////////////
  948. // This function emulates the behavior of
  949. // the Javascript 1.1 array.join() function
  950. ////////////////////////////////////////////
  951. function joinOld(theArray, Sep) {
  952.   Sep = Sep.substring(0, 1);
  953.   
  954.   if (theArray.length == 0) 
  955.     NewString = '';
  956.   else 
  957.     NewString = theArray[0];
  958.   
  959.   for (var i = 1; i < theArray.length; i++) {
  960.     NewString = NewString + Sep + theArray[i];
  961.   }
  962.   
  963.   return NewString;
  964. }
  965.  
  966.  
  967.