title: xml2json - "X2JS is not defined"
body: <p>I'm using xml2json for the first time to get an review feed to populate on a website and I keep getting errors such as;</p>
  
  <blockquote>
    <p>Uncaught ReferenceError: X2JS is not defined</p>
  </blockquote>
  
  <p>and </p>
  
  <blockquote>
    <p>Uncaught TypeError: Cannot set property 'X2JS' of undefined</p>
  </blockquote>
  
  <p>I can't seem to find a solution, this is the code;</p>
  
  <pre><code>jQuery(document).ready(function() {
  //below here
  
  //API Feed for Testimonials
  
  (function (root, factory) {
       if (typeof define === "function" &amp;&amp; define.amd) {
           define([], factory);
       } else if (typeof exports === "object") {
           module.exports = factory();
       } else {
           root.X2JS = factory();
       }
   }(this, function () {
      return function (config) {
          'use strict';
  
          var VERSION = "1.2.0";
  
          config = config || {};
          initConfigDefaults();
          initRequiredPolyfills();
  
          function initConfigDefaults() {
              if(config.escapeMode === undefined) {
                  config.escapeMode = true;
              }
  
              config.attributePrefix = config.attributePrefix || "_";
              config.arrayAccessForm = config.arrayAccessForm || "none";
              config.emptyNodeForm = config.emptyNodeForm || "text";      
  
              if(config.enableToStringFunc === undefined) {
                  config.enableToStringFunc = true; 
              }
              config.arrayAccessFormPaths = config.arrayAccessFormPaths || []; 
              if(config.skipEmptyTextNodesForObj === undefined) {
                  config.skipEmptyTextNodesForObj = true;
              }
              if(config.stripWhitespaces === undefined) {
                  config.stripWhitespaces = true;
              }
              config.datetimeAccessFormPaths = config.datetimeAccessFormPaths || [];
  
              if(config.useDoubleQuotes === undefined) {
                  config.useDoubleQuotes = false;
              }
  
              config.xmlElementsFilter = config.xmlElementsFilter || [];
              config.jsonPropertiesFilter = config.jsonPropertiesFilter || [];
  
              if(config.keepCData === undefined) {
                  config.keepCData = false;
              }
          }
  
          var DOMNodeTypes = {
              ELEMENT_NODE       : 1,
              TEXT_NODE          : 3,
              CDATA_SECTION_NODE : 4,
              COMMENT_NODE       : 8,
              DOCUMENT_NODE      : 9
          };
  
          function initRequiredPolyfills() {      
          }
  
          function getNodeLocalName( node ) {
              var nodeLocalName = node.localName;         
              if(nodeLocalName == null) // Yeah, this is IE!! 
                  nodeLocalName = node.baseName;
              if(nodeLocalName == null || nodeLocalName=="") // =="" is IE too
                  nodeLocalName = node.nodeName;
              return nodeLocalName;
          }
  
          function getNodePrefix(node) {
              return node.prefix;
          }
  
          function escapeXmlChars(str) {
              if(typeof(str) == "string")
                  return str.replace(/&amp;/g, '&amp;amp;').replace(/&lt;/g, '&amp;lt;').replace(/&gt;/g, '&amp;gt;').replace(/"/g, '&amp;quot;').replace(/'/g, '&amp;apos;');
              else
                  return str;
          }
  
          function unescapeXmlChars(str) {
              return str.replace(/&amp;lt;/g, '&lt;').replace(/&amp;gt;/g, '&gt;').replace(/&amp;quot;/g, '"').replace(/&amp;apos;/g, "'").replace(/&amp;amp;/g, '&amp;');
          }
  
          function checkInStdFiltersArrayForm(stdFiltersArrayForm, obj, name, path) {
              var idx = 0;
              for(; idx &lt; stdFiltersArrayForm.length; idx++) {
                  var filterPath = stdFiltersArrayForm[idx];
                  if( typeof filterPath === "string" ) {
                      if(filterPath == path)
                          break;
                  }
                  else
                  if( filterPath instanceof RegExp) {
                      if(filterPath.test(path))
                          break;
                  }               
                  else
                  if( typeof filterPath === "function") {
                      if(filterPath(obj, name, path))
                          break;
                  }
              }
              return idx!=stdFiltersArrayForm.length;
          }
  
          function toArrayAccessForm(obj, childName, path) {
              switch(config.arrayAccessForm) {
                  case "property":
                      if(!(obj[childName] instanceof Array))
                          obj[childName+"_asArray"] = [obj[childName]];
                      else
                          obj[childName+"_asArray"] = obj[childName];
                      break;
                  /*case "none":
                      break;*/
              }
  
              if(!(obj[childName] instanceof Array) &amp;&amp; config.arrayAccessFormPaths.length &gt; 0) {
                  if(checkInStdFiltersArrayForm(config.arrayAccessFormPaths, obj, childName, path)) {
                      obj[childName] = [obj[childName]];
                  }           
              }
          }
  
          function fromXmlDateTime(prop) {
              // Implementation based up on http://stackoverflow.com/questions/8178598/xml-datetime-to-javascript-date-object
              // Improved to support full spec and optional parts
              var bits = prop.split(/[-T:+Z]/g);
  
              var d = new Date(bits[0], bits[1]-1, bits[2]);          
              var secondBits = bits[5].split("\.");
              d.setHours(bits[3], bits[4], secondBits[0]);
              if(secondBits.length&gt;1)
                  d.setMilliseconds(secondBits[1]);
  
              // Get supplied time zone offset in minutes
              if(bits[6] &amp;&amp; bits[7]) {
                  var offsetMinutes = bits[6] * 60 + Number(bits[7]);
                  var sign = /\d\d-\d\d:\d\d$/.test(prop)? '-' : '+';
  
                  // Apply the sign
                  offsetMinutes = 0 + (sign == '-'? -1 * offsetMinutes : offsetMinutes);
  
                  // Apply offset and local timezone
                  d.setMinutes(d.getMinutes() - offsetMinutes - d.getTimezoneOffset())
              }
              else
                  if(prop.indexOf("Z", prop.length - 1) !== -1) {
                      d = new Date(Date.UTC(d.getFullYear(), d.getMonth(), d.getDate(), d.getHours(), d.getMinutes(), d.getSeconds(), d.getMilliseconds()));                  
                  }
  
              // d is now a local time equivalent to the supplied time
              return d;
          }
  
          function checkFromXmlDateTimePaths(value, childName, fullPath) {
              if(config.datetimeAccessFormPaths.length &gt; 0) {
                  var path = fullPath.split("\.#")[0];
                  if(checkInStdFiltersArrayForm(config.datetimeAccessFormPaths, value, childName, path)) {
                      return fromXmlDateTime(value);
                  }
                  else
                      return value;           
              }
              else
                  return value;
          }
  
          function checkXmlElementsFilter(obj, childType, childName, childPath) {
              if( childType == DOMNodeTypes.ELEMENT_NODE &amp;&amp; config.xmlElementsFilter.length &gt; 0) {
                  return checkInStdFiltersArrayForm(config.xmlElementsFilter, obj, childName, childPath); 
              }
              else
                  return true;
          }   
  
          function parseDOMChildren( node, path ) {
              if(node.nodeType == DOMNodeTypes.DOCUMENT_NODE) {
                  var result = new Object;
                  var nodeChildren = node.childNodes;
                  // Alternative for firstElementChild which is not supported in some environments
                  for(var cidx=0; cidx &lt;nodeChildren.length; cidx++) {
                      var child = nodeChildren.item(cidx);
                      if(child.nodeType == DOMNodeTypes.ELEMENT_NODE) {
                          var childName = getNodeLocalName(child);
                          result[childName] = parseDOMChildren(child, childName);
                      }
                  }
                  return result;
              }
              else
              if(node.nodeType == DOMNodeTypes.ELEMENT_NODE) {
                  var result = new Object;
                  result.__cnt=0;
  
                  var nodeChildren = node.childNodes;
  
                  // Children nodes
                  for(var cidx=0; cidx &lt;nodeChildren.length; cidx++) {
                      var child = nodeChildren.item(cidx); // nodeChildren[cidx];
                      var childName = getNodeLocalName(child);
  
                      if(child.nodeType!= DOMNodeTypes.COMMENT_NODE) {
                          var childPath = path+"."+childName;
                          if (checkXmlElementsFilter(result,child.nodeType,childName,childPath)) {
                              result.__cnt++;
                              if(result[childName] == null) {
                                  result[childName] = parseDOMChildren(child, childPath);
                                  toArrayAccessForm(result, childName, childPath);                    
                              }
                              else {
                                  if(result[childName] != null) {
                                      if( !(result[childName] instanceof Array)) {
                                          result[childName] = [result[childName]];
                                          toArrayAccessForm(result, childName, childPath);
                                      }
                                  }
                                  (result[childName])[result[childName].length] = parseDOMChildren(child, childPath);
                              }
                          }
                      }                               
                  }
  
                  // Attributes
                  for(var aidx=0; aidx &lt;node.attributes.length; aidx++) {
                      var attr = node.attributes.item(aidx); // [aidx];
                      result.__cnt++;
                      result[config.attributePrefix+attr.name]=attr.value;
                  }
  
                  // Node namespace prefix
                  var nodePrefix = getNodePrefix(node);
                  if(nodePrefix!=null &amp;&amp; nodePrefix!="") {
                      result.__cnt++;
                      result.__prefix=nodePrefix;
                  }
  
                  if(result["#text"]!=null) {             
                      result.__text = result["#text"];
                      if(result.__text instanceof Array) {
                          result.__text = result.__text.join("\n");
                      }
                      //if(config.escapeMode)
                      //  result.__text = unescapeXmlChars(result.__text);
                      if(config.stripWhitespaces)
                          result.__text = result.__text.trim();
                      delete result["#text"];
                      if(config.arrayAccessForm=="property")
                          delete result["#text_asArray"];
                      result.__text = checkFromXmlDateTimePaths(result.__text, childName, path+"."+childName);
                  }
                  if(result["#cdata-section"]!=null) {
                      result.__cdata = result["#cdata-section"];
                      delete result["#cdata-section"];
                      if(config.arrayAccessForm=="property")
                          delete result["#cdata-section_asArray"];
                  }
  
                  if( result.__cnt == 0 &amp;&amp; config.emptyNodeForm=="text" ) {
                      result = '';
                  }
                  else
                  if( result.__cnt == 1 &amp;&amp; result.__text!=null  ) {
                      result = result.__text;
                  }
                  else
                  if( result.__cnt == 1 &amp;&amp; result.__cdata!=null &amp;&amp; !config.keepCData  ) {
                      result = result.__cdata;
                  }           
                  else            
                  if ( result.__cnt &gt; 1 &amp;&amp; result.__text!=null &amp;&amp; config.skipEmptyTextNodesForObj) {
                      if( (config.stripWhitespaces &amp;&amp; result.__text=="") || (result.__text.trim()=="")) {
                          delete result.__text;
                      }
                  }
                  delete result.__cnt;            
  
                  if( config.enableToStringFunc &amp;&amp; (result.__text!=null || result.__cdata!=null )) {
                      result.toString = function() {
                          return (this.__text!=null? this.__text:'')+( this.__cdata!=null ? this.__cdata:'');
                      };
                  }
  
                  return result;
              }
              else
              if(node.nodeType == DOMNodeTypes.TEXT_NODE || node.nodeType == DOMNodeTypes.CDATA_SECTION_NODE) {
                  return node.nodeValue;
              }   
          }
  
          function startTag(jsonObj, element, attrList, closed) {
              var resultStr = "&lt;"+ ( (jsonObj!=null &amp;&amp; jsonObj.__prefix!=null)? (jsonObj.__prefix+":"):"") + element;
              if(attrList!=null) {
                  for(var aidx = 0; aidx &lt; attrList.length; aidx++) {
                      var attrName = attrList[aidx];
                      var attrVal = jsonObj[attrName];
                      if(config.escapeMode)
                          attrVal=escapeXmlChars(attrVal);
                      resultStr+=" "+attrName.substr(config.attributePrefix.length)+"=";
                      if(config.useDoubleQuotes)
                          resultStr+='"'+attrVal+'"';
                      else
                          resultStr+="'"+attrVal+"'";
                  }
              }
              if(!closed)
                  resultStr+="&gt;";
              else
                  resultStr+="/&gt;";
              return resultStr;
          }
  
          function endTag(jsonObj,elementName) {
              return "&lt;/"+ (jsonObj.__prefix!=null? (jsonObj.__prefix+":"):"")+elementName+"&gt;";
          }
  
          function endsWith(str, suffix) {
              return str.indexOf(suffix, str.length - suffix.length) !== -1;
          }
  
          function jsonXmlSpecialElem ( jsonObj, jsonObjField ) {
              if((config.arrayAccessForm=="property" &amp;&amp; endsWith(jsonObjField.toString(),("_asArray"))) 
                      || jsonObjField.toString().indexOf(config.attributePrefix)==0 
                      || jsonObjField.toString().indexOf("__")==0
                      || (jsonObj[jsonObjField] instanceof Function) )
                  return true;
              else
                  return false;
          }
  
          function jsonXmlElemCount ( jsonObj ) {
              var elementsCnt = 0;
              if(jsonObj instanceof Object ) {
                  for( var it in jsonObj  ) {
                      if(jsonXmlSpecialElem ( jsonObj, it) )
                          continue;           
                      elementsCnt++;
                  }
              }
              return elementsCnt;
          }
  
          function checkJsonObjPropertiesFilter(jsonObj, propertyName, jsonObjPath) {
              return config.jsonPropertiesFilter.length == 0
                  || jsonObjPath==""
                  || checkInStdFiltersArrayForm(config.jsonPropertiesFilter, jsonObj, propertyName, jsonObjPath); 
          }
  
          function parseJSONAttributes ( jsonObj ) {
              var attrList = [];
              if(jsonObj instanceof Object ) {
                  for( var ait in jsonObj  ) {
                      if(ait.toString().indexOf("__")== -1 &amp;&amp; ait.toString().indexOf(config.attributePrefix)==0) {
                          attrList.push(ait);
                      }
                  }
              }
              return attrList;
          }
  
          function parseJSONTextAttrs ( jsonTxtObj ) {
              var result ="";
  
              if(jsonTxtObj.__cdata!=null) {                                      
                  result+="&lt;![CDATA["+jsonTxtObj.__cdata+"]]&gt;";                   
              }
  
              if(jsonTxtObj.__text!=null) {           
                  if(config.escapeMode)
                      result+=escapeXmlChars(jsonTxtObj.__text);
                  else
                      result+=jsonTxtObj.__text;
              }
              return result;
          }
  
          function parseJSONTextObject ( jsonTxtObj ) {
              var result ="";
  
              if( jsonTxtObj instanceof Object ) {
                  result+=parseJSONTextAttrs ( jsonTxtObj );
              }
              else
                  if(jsonTxtObj!=null) {
                      if(config.escapeMode)
                          result+=escapeXmlChars(jsonTxtObj);
                      else
                          result+=jsonTxtObj;
                  }
  
              return result;
          }
  
          function getJsonPropertyPath(jsonObjPath, jsonPropName) {
              if (jsonObjPath==="") {
                  return jsonPropName;
              }
              else
                  return jsonObjPath+"."+jsonPropName;
          }
  
          function parseJSONArray ( jsonArrRoot, jsonArrObj, attrList, jsonObjPath ) {
              var result = ""; 
              if(jsonArrRoot.length == 0) {
                  result+=startTag(jsonArrRoot, jsonArrObj, attrList, true);
              }
              else {
                  for(var arIdx = 0; arIdx &lt; jsonArrRoot.length; arIdx++) {
                      result+=startTag(jsonArrRoot[arIdx], jsonArrObj, parseJSONAttributes(jsonArrRoot[arIdx]), false);
                      result+=parseJSONObject(jsonArrRoot[arIdx], getJsonPropertyPath(jsonObjPath,jsonArrObj));
                      result+=endTag(jsonArrRoot[arIdx],jsonArrObj);
                  }
              }
              return result;
          }
  
          function parseJSONObject ( jsonObj, jsonObjPath ) {
              var result = "";    
  
              var elementsCnt = jsonXmlElemCount ( jsonObj );
  
              if(elementsCnt &gt; 0) {
                  for( var it in jsonObj ) {
  
                      if(jsonXmlSpecialElem ( jsonObj, it) || (jsonObjPath!="" &amp;&amp; !checkJsonObjPropertiesFilter(jsonObj, it, getJsonPropertyPath(jsonObjPath,it))) )
                          continue;           
  
                      var subObj = jsonObj[it];                       
  
                      var attrList = parseJSONAttributes( subObj )
  
                      if(subObj == null || subObj == undefined) {
                          result+=startTag(subObj, it, attrList, true);
                      }
                      else
                      if(subObj instanceof Object) {
  
                          if(subObj instanceof Array) {                   
                              result+=parseJSONArray( subObj, it, attrList, jsonObjPath );                    
                          }
                          else if(subObj instanceof Date) {
                              result+=startTag(subObj, it, attrList, false);
                              result+=subObj.toISOString();
                              result+=endTag(subObj,it);
                          }
                          else {
                              var subObjElementsCnt = jsonXmlElemCount ( subObj );
                              if(subObjElementsCnt &gt; 0 || subObj.__text!=null || subObj.__cdata!=null) {
                                  result+=startTag(subObj, it, attrList, false);
                                  result+=parseJSONObject(subObj, getJsonPropertyPath(jsonObjPath,it));
                                  result+=endTag(subObj,it);
                              }
                              else {
                                  result+=startTag(subObj, it, attrList, true);
                              }
                          }
                      }
                      else {
                          result+=startTag(subObj, it, attrList, false);
                          result+=parseJSONTextObject(subObj);
                          result+=endTag(subObj,it);
                      }
                  }
              }
              result+=parseJSONTextObject(jsonObj);
  
              return result;
          }
  
          this.parseXmlString = function(xmlDocStr) {
              var isIEParser = window.ActiveXObject || "ActiveXObject" in window;
              if (xmlDocStr === undefined) {
                  return null;
              }
              var xmlDoc;
              if (window.DOMParser) {
                  var parser=new window.DOMParser();          
                  var parsererrorNS = null;
                  // IE9+ now is here
                  if(!isIEParser) {
                      try {
                          parsererrorNS = parser.parseFromString("INVALID", "text/xml").getElementsByTagName("parsererror")[0].namespaceURI;
                      }
                      catch(err) {                    
                          parsererrorNS = null;
                      }
                  }
                  try {
                      xmlDoc = parser.parseFromString( xmlDocStr, "text/xml" );
                      if( parsererrorNS!= null &amp;&amp; xmlDoc.getElementsByTagNameNS(parsererrorNS, "parsererror").length &gt; 0) {
                          //throw new Error('Error parsing XML: '+xmlDocStr);
                          xmlDoc = null;
                      }
                  }
                  catch(err) {
                      xmlDoc = null;
                  }
              }
              else {
                  // IE :(
                  if(xmlDocStr.indexOf("&lt;?")==0) {
                      xmlDocStr = xmlDocStr.substr( xmlDocStr.indexOf("?&gt;") + 2 );
                  }
                  xmlDoc=new ActiveXObject("Microsoft.XMLDOM");
                  xmlDoc.async="false";
                  xmlDoc.loadXML(xmlDocStr);
              }
              return xmlDoc;
          };
  
          this.asArray = function(prop) {
              if (prop === undefined || prop == null)
                  return [];
              else
              if(prop instanceof Array)
                  return prop;
              else
                  return [prop];
          };
  
          this.toXmlDateTime = function(dt) {
              if(dt instanceof Date)
                  return dt.toISOString();
              else
              if(typeof(dt) === 'number' )
                  return new Date(dt).toISOString();
              else    
                  return null;
          };
  
          this.asDateTime = function(prop) {
              if(typeof(prop) == "string") {
                  return fromXmlDateTime(prop);
              }
              else
                  return prop;
          };
  
          this.xml2json = function (xmlDoc) {
              return parseDOMChildren ( xmlDoc );
          };
  
          this.xml_str2json = function (xmlDocStr) {
              var xmlDoc = this.parseXmlString(xmlDocStr);
              if(xmlDoc!=null)
                  return this.xml2json(xmlDoc);
              else
                  return null;
          };
  
          this.json2xml_str = function (jsonObj) {
              return parseJSONObject ( jsonObj, "" );
          };
  
          this.json2xml = function (jsonObj) {
              var xmlDocStr = this.json2xml_str (jsonObj);
              return this.parseXmlString(xmlDocStr);
          };
  
          this.getVersion = function () {
              return VERSION;
          };  
      }
  }))
  
  // Create x2js instance with default config
  var x2js = new X2JS();
  var xmlText = "";
  
  jQuery.getJSON( "https://service1.homepro.com/smart.asmx/GetFAP_ProfileReviewsJSON?bid=141772&amp;sort=1&amp;page=1", function( data ) {
      var xmlText = data,
      x2js = new X2JS(),
      jsonObj = x2js.xml_str2json( xmlText ),
      html = '&lt;div class="flex-wrapper"&gt;';
      // console.log(jsonObj.SMART);  
  
      jQuery.each( jsonObj.SMART.XMLJSON, function( key, answer ) {
          html += '&lt;div class="flex-shell testimonial"&gt;';
          html += '&lt;div class="flex-item"&gt;';
          html += '&lt;div&gt;';
          html += '&lt;span class="review-number"&gt;&lt;i&gt;' + answer.Quality + '&lt;/i&gt; Quality of work&lt;/span&gt;' ;
          html += '&lt;span class="review-number"&gt;&lt;i&gt;' + answer.Time + '&lt;/i&gt; Timeliness&lt;/span&gt;' ;
          html += '&lt;span class="review-number"&gt;&lt;i&gt;' + answer.Budget + '&lt;/i&gt; Value for Money&lt;/span&gt;' ;
          html += '&lt;span class="review-number"&gt;&lt;i&gt;' + answer.Courtesy + '&lt;/i&gt; Courtesy&lt;/span&gt;' ;
          html += '&lt;span class="review"&gt;' + answer.Testimonial + '&lt;/span&gt;' ;
          html += '&lt;span class="name"&gt;' + answer.RefName + ' - ' + answer.refDate + '&lt;/span&gt;';                            
          html += '&lt;/div&gt;';
          html += '&lt;/div&gt;';
          html += '&lt;/div&gt;';
      });
  
      jQuery('.start').html(html);
  });
  
  //above here
  });
  </code></pre>
  
  <p>Apologies if I've gone about this in the wrong way. I've done;</p>
  
  <blockquote>
    <p>npm install xml2json</p>
  </blockquote>
  
  <p>Which didn't flag up any errors but I still can't seem to get the data to load correctly. </p>