public virtual List<NavigationNode> FindMatches(
            NavigationNode[] allNodes,
            DeleteNavigationNodesDefinitionBase typedDefinition,
            Func<string, string> resolveTokenizedUrlAction)
        {
            var nodesToDelete = new List<NavigationNode>();

            foreach (var nodeMatch in typedDefinition.NavigationNodes)
            {
                var foundByTitle = false;

                // search by Title, first
                if (!string.IsNullOrEmpty(nodeMatch.Title))
                {
                    var nodeByTitle = allNodes.FirstOrDefault(f =>
                        string.Equals(f.Title, nodeMatch.Title, StringComparison.OrdinalIgnoreCase));

                    if (nodeByTitle != null)
                    {
                        foundByTitle = true;

                        if (!nodesToDelete.Contains(nodeByTitle))
                        {
                            nodesToDelete.Add(nodeByTitle);
                        }
                    }
                }

                // give a try by Url, then
                if (!foundByTitle && !string.IsNullOrEmpty(nodeMatch.Url))
                {
                    var matchUrl = resolveTokenizedUrlAction(nodeMatch.Url);

                    // special char resolution, manual fix to avoid
                    // Add more tests for DeleteXXXnavigationNode scenarios #864
                    // https://github.com/SubPointSolutions/spmeta2/issues/864
                    matchUrl = HttpUtility.HtmlEncode(matchUrl);

                    var nodeByUrl = allNodes.FirstOrDefault(f =>
                        !string.IsNullOrEmpty(f.Url)
                        && f.Url.EndsWith(matchUrl, StringComparison.OrdinalIgnoreCase));

                    if (nodeByUrl != null)
                    {
                        if (!nodesToDelete.Contains(nodeByUrl))
                            nodesToDelete.Add(nodeByUrl);
                    }
                }
            }
            return nodesToDelete;
        }