protected virtual void ProcessNodes(IEnumerable <SiteMapNode> nodes, SiteMapNode rootNode)
        {
            foreach (var node in nodes)
            {
                var siteMapNode = GetSiteMapNodeFromJSONNode(node, rootNode);

                if (!string.IsNullOrEmpty(siteMapNode.DynamicNodeProvider))
                {
                    // has dynamic node provider
                    var dynamicNodes = DynamicNodeBuilder.BuildDynamicNodes(siteMapNode.DynamicNodeProvider, rootNode);

                    // add to root node
                    rootNode.ChildNodes.AddRange(dynamicNodes);

                    // add non-dynamic children for every dynamic node
                    ProcessNodes(dynamicNodes, rootNode);
                }
                else
                {
                    rootNode.ChildNodes.Add(siteMapNode);

                    ProcessNodes(node.ChildNodes, siteMapNode);
                }
            }
        }
        /// <summary>
        /// Recursively process our XML document, parsing our siteMapNodes and dynamicNode(s).
        /// </summary>
        /// <param name="rootNode">The main root siteMap node.</param>
        /// <param name="rootElement">the main root XML element.</param>
        protected virtual void ProcessXmlNodes(SiteMapNode rootNode, XElement rootElement)
        {
            // loop through each element below the current root element
            foreach (XElement node in rootElement.Elements())
            {
                SiteMapNode childNode;
                if (!node.Name.LocalName.Equals(nodeName, StringComparison.OrdinalIgnoreCase))
                {
                    throw new Exception($"Element of type {node.Name.LocalName} is an invalid node.");
                }

                // if this is a normal mvcSieMapNode then map the xml element
                // to an mvcSiteMapNode, and add the node to the current root.
                childNode = GetSiteMapNodeFromXmlElement(node, rootNode);

                if (!string.IsNullOrEmpty(childNode.DynamicNodeProvider))
                {
                    // has dynamic node provider
                    var dynamicNodes = DynamicNodeBuilder.BuildDynamicNodes(childNode.DynamicNodeProvider, rootNode);

                    // add to root node
                    rootNode.ChildNodes.AddRange(dynamicNodes);

                    // add non-dynamic children for every dynamic node
                    foreach (var dynamicNode in dynamicNodes)
                    {
                        ProcessXmlNodes(dynamicNode, node);
                    }
                }
                else
                {
                    rootNode.ChildNodes.Add(childNode);

                    ProcessXmlNodes(childNode, node);
                }
            }
        }