Advertisement
Handoncloud

Untitled

Aug 1st, 2016
181
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. window.parseXML = (function() {
  2.  
  3.     var xnode = function(name, attributes) {
  4.  
  5.         // Node attributes
  6.         this.attributes = attributes || {};
  7.  
  8.         // Children nodes, initially empty
  9.         this.children = [];
  10.  
  11.         // Node name
  12.         this.name = name;
  13.  
  14.     },
  15.  
  16.     xtext = function(value) {
  17.  
  18.         this.value = value;
  19.  
  20.     };
  21.  
  22.     function forEachNode(node, callback) {
  23.  
  24.         // Iterate each node and execute callback
  25.         for(var x = 0, childNode; childNode = node.children[x]; x ++) callback(childNode);
  26.  
  27.     }
  28.  
  29.     xnode['prototype'] = {
  30.  
  31.         find: function(name) {
  32.  
  33.             // All elements got by name
  34.             var result = [];
  35.  
  36.             // Iterate each child of node
  37.             function checkChildren(node) {
  38.  
  39.                 forEachNode(node, function(childNode) {
  40.  
  41.                     // Check if children have tag name
  42.                     if(childNode instanceof xnode) checkChildren(childNode);
  43.  
  44.                     // Check if current node has tag name
  45.                     if(childNode.name === name) result.push(childNode);
  46.  
  47.                 });
  48.  
  49.             }
  50.  
  51.             checkChildren(this);
  52.  
  53.             return result;
  54.  
  55.         }
  56.  
  57.     };
  58.  
  59.     // parseXML :: function
  60.     return (function(Buf) {
  61.  
  62.         // XML root
  63.         var chunk = new xnode();
  64.  
  65.         // Inner location
  66.         var locations = [ chunk ];
  67.  
  68.         // Consume characters until callback returns a positive value
  69.         function consumeUntil(fnc, except) {
  70.  
  71.             var string = '',
  72.                 hasEnded = false;
  73.  
  74.             var hasExc = typeof except === 'function';
  75.  
  76.             // Iterate characters
  77.             for(; CharCode = Buf.charCodeAt(I); I ++) {
  78.  
  79.                 if( hasExc ? !except() : true ) {
  80.  
  81.                     // Check if function returns falsy value
  82.                     if(!fnc()) string += String.fromCharCode(CharCode)
  83.  
  84.                     // Or end the loop
  85.                     ;else {
  86.  
  87.                         hasEnded = true;
  88.  
  89.                         break;
  90.  
  91.                     }
  92.  
  93.                 }
  94.  
  95.             }
  96.  
  97.             return {
  98.  
  99.                 hasEnded: hasEnded,
  100.  
  101.                 string: string
  102.  
  103.             };
  104.         }
  105.  
  106.         // Check if string is space or line terminator
  107.         function isBlankToken() {
  108.             return CharCode === 9 || CharCode === 10 || CharCode === 13 || CharCode === 32;
  109.         }
  110.  
  111.         // Check if string is start of a node name
  112.         function isNodeNameStart() {
  113.                    // A - Z
  114.             return (CharCode >= 65 && CharCode <= 90) ||
  115.                    // a - z
  116.                    (CharCode >= 97 && CharCode <= 122);
  117.         }
  118.  
  119.         // Check if string is part of a node name
  120.         function isNodeNamePart() {
  121.                    // A - Z
  122.             return (CharCode >= 65 && CharCode <= 90) ||
  123.                    // a - z
  124.                    (CharCode >= 97 && CharCode <= 122) ||
  125.                    // 0 - 9
  126.                    (CharCode >= 48 && CharCode <= 57) ||
  127.                    // -
  128.                    CharCode === 45 ||
  129.                    // .
  130.                    CharCode === 46 ||
  131.                    // :
  132.                    CharCode === 58 ||
  133.                    // _
  134.                    CharCode === 95;
  135.         }
  136.  
  137.         // Move to the next string
  138.         function moveToNextChar() {
  139.             I ++;
  140.             CharCode = Buf.charCodeAt(I);
  141.         }
  142.  
  143.         // Iterate characters
  144.         for(var I = 0, CharCode; CharCode = Buf.charCodeAt(I); I ++) {
  145.  
  146.             // Check if string is '<'
  147.             if(CharCode === 60) {
  148.  
  149.                 // Move to the next string
  150.                 moveToNextChar();
  151.  
  152.                 // Check if the next string is '/'
  153.                 if(CharCode === 47) {
  154.  
  155.                     var nameSearch = consumeUntil(function() {
  156.                         return CharCode === 62;
  157.                     }, function() {
  158.                         return isBlankToken();
  159.                     });
  160.  
  161.                     // Get the index of the last location
  162.                     var lastInnerIndex = locations.length - 1;
  163.  
  164.                     // Check if the string has been correctly consumed (ended with '>') and check if it's not empty;
  165.                     // And check if the string is equal to the name of the location node.
  166.                     if(nameSearch.hasEnded &&
  167.                        nameSearch.string.length > 0 &&
  168.                        nameSearch.string === locations[lastInnerIndex].name) {
  169.  
  170.                         // Then close the node path
  171.                         locations.splice(lastInnerIndex, 1);
  172.  
  173.                     }
  174.  
  175.                 }
  176.                 // Check if the string is '!'
  177.                 else if(CharCode === 33 || CharCode === 63) { // Comment; while the parser isn't update, every tag like <? is gonna be ignored.
  178.                     // Check if the comment starts with --
  179.                     if(CharCode !== 63 && Buf.substring(I + 1, I + 3) === '--') {
  180.                         I += 2;
  181.                         // Then the comment ends with -->
  182.                         consumeUntil(function() {
  183.  
  184.                             return CharCode === 45 && Buf.substring(I + 1, I + 3) === '->';
  185.  
  186.                         });
  187.                         I += 2;
  188.                     }
  189.                     // Else the comment ends at '>' or until the end of the XML string
  190.                     else {
  191.  
  192.                         consumeUntil(function() {
  193.  
  194.                             return CharCode === 62;
  195.  
  196.                         });
  197.  
  198.                     }
  199.                 }
  200.                 // Check if the string is start of a node name
  201.                 else if(isNodeNameStart()) {
  202.  
  203.                     // The node attributes object
  204.                     var attributes = {};
  205.  
  206.                     var nodeNameStart = String.fromCharCode(CharCode);
  207.  
  208.                     // Move to next character to not count with the name start
  209.                     moveToNextChar();
  210.  
  211.                     // Get the following string of the node name
  212.                     var nodeName = nodeNameStart + consumeUntil(function() {
  213.  
  214.                         return !isNodeNamePart();
  215.  
  216.                     }).string;
  217.  
  218.                     // Consume node inner, or ignore the inner case there's a typo
  219.                     var reconsume = function() {
  220.  
  221.                         // NOTE
  222.                         // Char 47 = /
  223.                         // Char 62 = >
  224.  
  225.                         // End node as a path >
  226.                         if(CharCode === 62) {
  227.  
  228.                             // Create the node element
  229.                             var node = new xnode(nodeName, attributes);
  230.  
  231.                             // Push the node to the last path
  232.                             locations[locations.length - 1].children.push(node);
  233.  
  234.                             // Create node path where goes the children
  235.                             locations.push(node);
  236.  
  237.                         }
  238.                         // End node without path />
  239.                         else if(CharCode === 47) {
  240.  
  241.                             moveToNextChar();
  242.  
  243.                             // Check if next char is >
  244.                             if(CharCode === 62) {
  245.  
  246.                                 // Create the node element
  247.                                 var node = new xnode(nodeName, attributes);
  248.  
  249.                                 // Push the node to the last path
  250.                                 locations[locations.length - 1].children.push(node);
  251.  
  252.                             }
  253.  
  254.                         }
  255.                         // Search for attributes
  256.                         else {
  257.  
  258.                             // Skip blank or unconsiderable characters
  259.                             var skipSearch = consumeUntil(function() {
  260.  
  261.                                 return !isBlankToken() || CharCode === 47 || CharCode === 62;
  262.  
  263.                             });
  264.  
  265.                             // Check if attribute start has BEEN declared!
  266.                             if(skipSearch.hasEnded && CharCode !== 62) {
  267.  
  268.                                 // Get full attribute name
  269.                                 var attrName = consumeUntil(function() {
  270.  
  271.                                     return isBlankToken() || CharCode === 47 || CharCode === 62 || CharCode === 61;
  272.  
  273.                                 }).string;
  274.  
  275.                                 // Set the attribute value as true while not defined
  276.                                 attributes[attrName] = true;
  277.  
  278.                                 // Skip blank characters
  279.                                 consumeUntil(function() {
  280.  
  281.                                     return !isBlankToken();
  282.  
  283.                                 });
  284.  
  285.                                 // Check if char is assign
  286.                                 if(CharCode === 61) {
  287.  
  288.                                     moveToNextChar();
  289.  
  290.                                     // Check if next character is not blank
  291.                                     if(!isBlankToken() && CharCode !== 34 && CharCode !== 39) {
  292.  
  293.                                         // Then consume free value
  294.                                         var frAttrValue = consumeUntil(function() {
  295.  
  296.                                             return isBlankToken() || CharCode === 47 || CharCode === 62;
  297.  
  298.                                         }).string;
  299.  
  300.                                         attributes[attrName] = frAttrValue || true;
  301.  
  302.                                         reconsume();
  303.  
  304.                                     }
  305.                                     else{
  306.  
  307.                                         // Then skip blank characters again
  308.                                         consumeUntil(function() {
  309.  
  310.                                             return !isBlankToken();
  311.  
  312.                                         });
  313.  
  314.                                         // Check if string is " or '
  315.                                         if(CharCode === 34 || CharCode === 39) {
  316.  
  317.                                             // Memorize quote
  318.                                             var quote = CharCode;
  319.  
  320.                                             // Skip the quote
  321.                                             moveToNextChar();
  322.  
  323.                                             // Then consume characters until quote happens
  324.                                             var attrValueSearch = consumeUntil(function() {
  325.  
  326.                                                 return CharCode === quote;
  327.  
  328.                                             });
  329.  
  330.                                             // Skip the final quote, also
  331.                                             moveToNextChar();
  332.  
  333.                                             if(attrValueSearch.hasEnded) {
  334.  
  335.                                                 attributes[attrName] = attrValueSearch.string || true;
  336.                                                 reconsume()
  337.  
  338.                                             }
  339.  
  340.                                         }else reconsume();
  341.  
  342.                                     }
  343.  
  344.                                 }
  345.                                 else{
  346.  
  347.                                     reconsume();
  348.  
  349.                                 }
  350.                             }
  351.                         }
  352.                     };
  353.  
  354.                     reconsume();
  355.  
  356.                 }
  357.                 // Else ignore the tag
  358.             }
  359.             else{
  360.  
  361.                 var lastCharCode,
  362.  
  363.                 text = consumeUntil(function() {
  364.  
  365.                     return CharCode === 60;
  366.  
  367.                 }, function() {
  368.  
  369.                     var allowSpace = (lastCharCode === 9 || lastCharCode === 32) &&
  370.                                      (CharCode === 9 || CharCode === 32) ? false : true ;
  371.  
  372.                     lastCharCode = CharCode;
  373.                     return (CharCode === 10 && CharCode === 13) || !allowSpace;
  374.  
  375.                 }).string;
  376.  
  377.                 // Decrease index to not bug a node
  378.                 I --;
  379.  
  380.                 if(text.length > 0) {
  381.  
  382.                     // Create the text node
  383.                     var textNode = new xtext(text);
  384.  
  385.                     // Push the text node to the last path
  386.                     locations[locations.length - 1].children.push(textNode);
  387.  
  388.                 }
  389.             }
  390.         }
  391.  
  392.         return chunk;
  393.  
  394.     });
  395.  
  396. })();
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement