Name

global.StandardDiffer

Description

Diff the entire content of an xml file..

Script

var StandardDiffer = Class.create();

StandardDiffer.prototype = Object.extendsObject(Differ, {

  diffXML: function(root1, root2){
      var length1 = root1.getChildNodes().getLength();
      var length2 = root2.getChildNodes().getLength();
      var action =  this._getActionCompare(root1, root2);
      if (root1.getTagName() != "record_update") {
          var diff = this._diffUpdateXMLString(root1, root2, false);
          if (diff == "") 
              return this._noInfo();
          return action + diff;
      }
      if (length1 > length2) 
          return action + this._diffAllNodes(root1, root2, length1, true);
      else 
          return action + this._diffAllNodes(root2, root1, length2, false);
  },
  
  diffUpdateSet: function(root1){
      var gr = this._getParentRecord(root1);
      var root2;
      if (gr.next()) {
          var xmlSerializer = new GlideRecordXMLSerializer();
          var xml = xmlSerializer.serialize(gr);
          root2 = this._getRoot(xml);
          return this.diffXML(root2, root1);
      }
      else {
          return this._noInfo();
      }
  },
  
  getURL: function(root){
      var sys_id = root.getElementsByTagName("sys_id").item(0).getFirstChild().getNodeValue();
      return root.getTagName() + ".do?sys_id=" + sys_id;
  },
  
  _diffAllNodes: function(root1, root2, length, left2right){
      var result = "";
      for (var i = 0; i < length; i++) {
          if (root1.getChildNodes().item(i).getNodeType() == 3) 
              continue;
          var element = root1.getChildNodes().item(i);
          if (left2right) 
              result += this._diffUpdateXMLString(element, this._getMatchingElement(element, root2), false);
          else 
              result += this._diffUpdateXMLString(this._getMatchingElement(element, root2), element, false);
      }
      if (result == "") 
          return this._noInfo();
      return result;
  },
  
  _diffUpdateXMLString: function(item1, item2, showMatching){
      if (showMatching == null) 
          showMatching = false;
      if ((item1 == null || item1.getChildNodes().getLength() == 0)
          && (item2 == null || item2.getChildNodes().getLength() == 0))
          return "";
      if (item1 == null || item1.getChildNodes().getLength() == 0)
          return this._diffAddedElement(item2, true);
      if (item2 == null || item2.getChildNodes().getLength() == 0)
          return this._diffAddedElement(item1, false);
      var elements1 = item1.getChildNodes();
      var elements2 = item2.getChildNodes();
      var result = "";
      var multipleLineResults = "";
      for (var i = 0; i < elements1.getLength(); i++) {
          var found = false;
          var name = "";
          for (var n = 0; n < elements2.getLength(); n++) {
              if (elements1.item(i).getNodeName() != elements2.item(n).getNodeName()) 
                  continue;
              else {
                  var text1 = elements1.item(i).getFirstChild();
                  var text2 = elements2.item(n).getFirstChild();
                  name = elements1.item(i).getTagName();
                  if (!this._ignoreField(name))
                     found = true;
              }
          }
          if (!found) 
              continue;
          var textValue1 = " ";
          var textValue2 = " ";
          if (text1 != null)
             textValue1 = text1.getNodeValue() + "";
          if (text2 != null) 
             textValue2 = text2.getNodeValue() + "";
          var diffResult = this.diff(textValue1, textValue2, name, showMatching) + "";
          if (diffResult.match('<td class="count">2:</td>') != null) 
             multipleLineResults += diffResult + "<td class='zebra' colspan=5></td>";
          else 
             result += diffResult;
          
      }
      if (result == "" && multipleLineResults == "" && showMatching == false) 
          return this._diffUpdateXMLString(item1, item2, true);
      return result + multipleLineResults;
  },

  /*
   * Ignore fields that give no value to the user.
   * for example sys_mod_count always shows up because its always changed  
   */
  _ignoreField: function(name) {
      if (name == "sys_mod_count")
          return true;

      return false;
  },
  
  _getMatchingElement: function(item1, root2){
      var sys_id1;
      for (var i = 0; i < item1.getChildNodes().getLength(); i++) 
          if (item1.getChildNodes().item(i).getTagName() == "sys_id") 
              sys_id1 = item1.getChildNodes().item(i).getFirstChild().getNodeValue();
      var childNodes = root2.getChildNodes();
      for (var i = 0; i < childNodes.getLength(); i++) {
          var element = childNodes.item(i);
          for (var n = 0; n < element.getChildNodes().getLength(); n++) 
              if (element.item(n).getTagName() == "sys_id") {
                  if (sys_id1 == element.item(n).getFirstChild().getNodeValue()) 
                      return element;
              }
      }
      return null;
  },
  
  _diffAddedElement: function(item1, isSecond){
      var result = "";
      var elements1 = item1.getChildNodes();
      for (var i = 0; i < elements1.getLength(); i++) {
          var text1 = elements1.item(i).getChildNodes().item(0);
          if (text1 != null) {
  			if (isSecond) {
  				result += this.diff("", text1.getNodeValue() + "", elements1.item(i).getTagName(), true) + "";
  			}
  			else {
  		    	result += this.diff(text1.getNodeValue() + "", "", elements1.item(i).getTagName(), true) + "";
  			}
  		}
      }
      return result;
  },
  _getParentRecord: function(root){
      var sys_ids = root.getElementsByTagName("sys_id");
      
      if (sys_ids.getLength() < 1) 
          var sys_id = "";
      else 
          var sys_id = sys_ids.item(sys_ids.getLength() - 1).getFirstChild().getNodeValue();
      var gr = new GlideRecord(root.getTagName());
      gr.query("sys_id", sys_id + "");
      return gr;
  }
});

Sys ID

87c609c20a0a0bb00023ca6d9e5f76f9

Offical Documentation

Official Docs: