<commit_before>var xmldom = require("xmldom"), fs = require("fs");

function visit (array, element) {
  array.push({ start: true, element: element, nodeType: 1 });
  for (var child = element.firstChild; child; child = child.nextSibling) {
    if (child.nodeType == 1) {
      visit(array, child);    
    } else {
      array.push(child);
    } 
  }
  array.push({ start: false, element: element, nodeType: 1 });
  return array;
}

function flatten (doc) {
  return visit([], doc.documentElement || doc);
  
}

function attributes (element) {
  var attrs = {}, name, attr, i, I;
  for (i = 0, I = element.attributes.length; i < I; i++) {
    attr = element.attributes.item(i);
    name = attr.localName;
    if (attr.namespaceURI) name += ":(" + attr.namespaceURI + ")";
    attrs[name] = attr;
  }
  return attrs;
}

function abend(message) {
  return false;
  throw new Error(message);
}

function compare (actual, expected) {
  if (typeof expected == "string") {
    expected = new (xmldom.DOMParser)().parseFromString(expected).documentElement;
  }
  var e, a, aa, ea, name, at = [], et = [], remainder;
  actual = flatten(actual);
  expected = flatten(expected);
  a = actual.shift();
  while (expected.length) {
    e = expected.shift();
    switch (e.nodeType) {
    case 1:
      while (a.nodeType == 3 && actual.length) {
        at.push(a.nodeValue);
        a = actual.shift();
      }
      if (a.nodeType != 1) return abend();
      if (a.start != e.start) return abend();
      if (at.join("").trim() != et.join("").trim()) return abend();
      a = a.element;
      e = e.element;
      aa = attributes(a);
      ea = attributes(e);
      for (name in ea) {
        if (!aa[name]) return abend(name);
        if (ea[name].nodeValue != aa[name].nodeValue) return abend();
      }
      at.length = et.length = 0;
      a = actual.shift();
      break;
    case 3:
      et.push(e.nodeValue);
      break;
    default:
      throw new Error("Unexpected nodeType: " + e.nodeType);
    }
  }
  while (actual.length) {
    a = actual.shift();
    if (a.nodeType != 3 || a.nodeValue.trim() != "") return abend();
  }
  while (expected.length) {
    e = expected.shift();
    if (e.nodeType != 3 || e.nodeValue.trim() != "") return abend();
  }
  return true;
}

module.exports = compare;<commit_msg>Show path in expected XML that does not match.<commit_after>var xmldom = require("xmldom"), fs = require("fs");

function visit (array, element) {
  array.push({ start: true, element: element, nodeType: 1 });
  for (var child = element.firstChild; child; child = child.nextSibling) {
    if (child.nodeType == 1) {
      visit(array, child);    
    } else {
      array.push(child);
    } 
  }
  array.push({ start: false, element: element, nodeType: 1 });
  return array;
}

function flatten (doc) {
  return visit([], doc.documentElement || doc);
  
}

function attributes (element) {
  var attrs = {}, name, attr, i, I;
  for (i = 0, I = element.attributes.length; i < I; i++) {
    attr = element.attributes.item(i);
    name = attr.localName;
    if (attr.namespaceURI) name += ":(" + attr.namespaceURI + ")";
    attrs[name] = attr;
  }
  return attrs;
}

function name (node) {
  return node.localName + (node.namespaceURI ? '(' + node.namespaceURI + ')' : '');
}

function abend(e) {
  var stack = [], attrs = [], e = e.element, i;
  do {
    attrs.length = 0;
    for (i = 0; i < e.attributes.length; i++) {
      attrs.push(name(e.attributes[i]) + '=' + e.attributes[i].nodeValue)
    }
    stack.unshift(name(e) + (attrs.length ? '[' + (attrs.join(' ')) + ']' : ''));
  } while ((e = e.parentNode) && e.nodeType == 1);
  throw new Error(stack.join('/'));
}

function compare (actual, expected) {
  if (typeof expected == "string") {
    expected = new (xmldom.DOMParser)().parseFromString(expected).documentElement;
  }
  var e, a, aa, ea, name, at = [], et = [], remainder;
  actual = flatten(actual);
  expected = flatten(expected);
  a = actual.shift();
  while (expected.length) {
    e = expected.shift();
    switch (e.nodeType) {
    case 1:
      while (a.nodeType == 3 && actual.length) {
        at.push(a.nodeValue);
        a = actual.shift();
      }
      if (a.nodeType != 1) return abend(e);
      if (a.start != e.start) return abend(e);
      if (at.join("").trim() != et.join("").trim()) return abend(e);
      a = a.element;
      e = e.element;
      aa = attributes(a);
      ea = attributes(e);
      for (name in ea) {
        if (!aa[name]) return abend(e);
        if (ea[name].nodeValue != aa[name].nodeValue) return abend(e);
      }
      at.length = et.length = 0;
      a = actual.shift();
      break;
    case 3:
      et.push(e.nodeValue);
      break;
    default:
      throw new Error("Unexpected nodeType: " + e.nodeType);
    }
  }
  while (actual.length) {
    a = actual.shift();
    if (a.nodeType != 3 || a.nodeValue.trim() != "") return abend(e);
  }
  while (expected.length) {
    e = expected.shift();
    if (e.nodeType != 3 || e.nodeValue.trim() != "") return abend(e);
  }
  return true;
}

module.exports = compare;
{'fraction_non_alphanumeric': 0.1801022414471097, 'fraction_numerical': 0.004915454187966968, 'mean_word_length': 2.707725947521866, 'pattern_counts': {'":': 2, '<': 6, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 6}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1915393', 'n_tokens_mistral': 1778, 'n_tokens_neox': 1742, 'n_words': 435}