lib/signed-xml.js
function findAncestorNs(doc, docSubsetXpath){
  var docSubset = xpath.select(docSubsetXpath, doc);
  
  if(!Array.isArray(docSubset) || docSubset.length < 1){
    return [];
  }
  
  // Remove duplicate on ancestor namespace
  var ancestorNs = collectAncestorNamespaces(docSubset[0]);
  var ancestorNsWithoutDuplicate = [];
  for(var i=0;i<ancestorNs.length;i++){
    var notOnTheList = true;
    for(var v in ancestorNsWithoutDuplicate){
      if(ancestorNsWithoutDuplicate[v].prefix === ancestorNs[i].prefix){
        notOnTheList = false;
        break;
      }
    }
    
    if(notOnTheList){
      ancestorNsWithoutDuplicate.push(ancestorNs[i]);
    }
  }
  
  // Remove namespaces which are already declared in the subset with the same prefix
  var returningNs = [];
  var subsetAttributes = docSubset[0].attributes;
  for(var j=0;j<ancestorNsWithoutDuplicate.length;j++){
    var isUnique = true;
    for(var k=0;k<subsetAttributes.length;k++){
      var nodeName = subsetAttributes[k].nodeName;
      if(nodeName.search(/^xmlns:/) === -1) continue;
      var prefix = nodeName.replace(/^xmlns:/, "");
      if(ancestorNsWithoutDuplicate[j].prefix === prefix){
        isUnique = false;
        break;
      }
    }
  
    if(isUnique){
      returningNs.push(ancestorNsWithoutDuplicate[j]);
    }
  }
  
  return returningNs;
}
function findAncestorNs(doc, docSubsetXpath){
  var docSubset = xpath.select(docSubsetXpath, doc);
  
  if(!Array.isArray(docSubset) || docSubset.length < 1){
    return [];
  }
  
  // Remove duplicate on ancestor namespace
  var ancestorNs = collectAncestorNamespaces(docSubset[0]);
  var ancestorNsWithoutDuplicate = [];
  for(var i=0;i<ancestorNs.length;i++){
    var notOnTheList = true;
    for(var v in ancestorNsWithoutDuplicate){
      if(ancestorNsWithoutDuplicate[v].prefix === ancestorNs[i].prefix){
        notOnTheList = false;
        break;
      }
    }
    
    if(notOnTheList){
      ancestorNsWithoutDuplicate.push(ancestorNs[i]);
    }
  }
  
  // Remove namespaces which are already declared in the subset with the same prefix
  var returningNs = [];
  var subsetAttributes = docSubset[0].attributes;
  for(var j=0;j<ancestorNsWithoutDuplicate.length;j++){
    var isUnique = true;
    for(var k=0;k<subsetAttributes.length;k++){
      var nodeName = subsetAttributes[k].nodeName;
      if(nodeName.search(/^xmlns:/) === -1) continue;
      var prefix = nodeName.replace(/^xmlns:/, "");
      if(ancestorNsWithoutDuplicate[j].prefix === prefix){
        isUnique = false;
        break;
      }
    }
  
    if(isUnique){
      returningNs.push(ancestorNsWithoutDuplicate[j]);
    }
  }
  
  return returningNs;
}
function findAncestorNs ( doc , docSubsetXpath ) { var docSubset = xpath . select ( docSubsetXpath , doc ) ; if ( ! Array . isArray ( docSubset ) || docSubset . length < 1 ) { return [ ] ; } // Remove duplicate on ancestor namespace var ancestorNs = collectAncestorNamespaces ( docSubset [ 0 ] ) ; var ancestorNsWithoutDuplicate = [ ] ; for ( var i = 0 ; i < ancestorNs . length ; i ++ ) { var notOnTheList = true ; for ( var v in ancestorNsWithoutDuplicate ) { if ( ancestorNsWithoutDuplicate [ v ] . prefix === ancestorNs [ i ] . prefix ) { notOnTheList = false ; break ; } } if ( notOnTheList ) { ancestorNsWithoutDuplicate . push ( ancestorNs [ i ] ) ; } } // Remove namespaces which are already declared in the subset with the same prefix var returningNs = [ ] ; var subsetAttributes = docSubset [ 0 ] . attributes ; for ( var j = 0 ; j < ancestorNsWithoutDuplicate . length ; j ++ ) { var isUnique = true ; for ( var k = 0 ; k < subsetAttributes . length ; k ++ ) { var nodeName = subsetAttributes [ k ] . nodeName ; if ( nodeName . search ( / ^xmlns: / ) === - 1 ) continue ; var prefix = nodeName . replace ( / ^xmlns: / , "" ) ; if ( ancestorNsWithoutDuplicate [ j ] . prefix === prefix ) { isUnique = false ; break ; } } if ( isUnique ) { returningNs . push ( ancestorNsWithoutDuplicate [ j ] ) ; } } return returningNs ; }
Extract ancestor namespaces in order to import it to root of document subset
which is being canonicalized for non-exclusive c14n.

@param {object} doc - Usually a product from `new DOMParser().parseFromString()`
@param {string} docSubsetXpath - xpath query to get document subset being canonicalized
@returns {Array} i.e. [{prefix: "saml", namespaceURI: "urn:oasis:names:tc:SAML:2.0:assertion"}]
Extract ancestor namespaces in order to import it to root of document subset which is being canonicalized for non - exclusive c14n .