/// <summary>
        /// Orders and beautifies an XML document.
        /// </summary>
        /// <param name="source">The source XML document to order and beautify.</param>
        /// <param name="extension">The extension.  Used to determine tab spacing.</param>
        /// <returns>The text of the scrubbed and beautified document.</returns>
        private static string ScrubDocument(string source, string extension)
        {
            // Used to write the final document in the form of a long string.
            using (StringWriter stringWriter = new StringWriter(CultureInfo.InvariantCulture))
            {
                try
                {
                    // Read the source document.
                    using (StringReader stringReader = new StringReader(source))
                    {
                        // Create an XML document from the source string.
                        XDocument sourceDocument = XDocument.Load(stringReader, LoadOptions.PreserveWhitespace);

                        // Create a new target document.
                        XDocument targetDocument = new XDocument();

                        // Copy the declaration.
                        if (sourceDocument.Declaration != null)
                        {
                            targetDocument.Declaration = new XDeclaration(sourceDocument.Declaration);
                        }

                        // This will order all the attributes in the document in alphabetical order.  Note that the elements can't be similarly
                        // ordered because this could produce forward reference errors.
                        FormatXmlCommand.RecurseIntoDocument(sourceDocument.Root, targetDocument);

                        // This is used to make special consideration for XALM files.
                        bool isXaml = extension == ".XAML";

                        // Beautify and save the target document when it has been ordered.
                        XmlFormattedWriterSettings xmlFormattedWriterSettings = new XmlFormattedWriterSettings
                        {
                            Encoding           = Encoding.UTF8,
                            OmitXmlDeclaration = isXaml,
                            TabSize            = isXaml ? 4 : 2,
                        };
                        XmlWriter xmlWriter = XmlFormattedWriter.Create(stringWriter, xmlFormattedWriterSettings);
                        targetDocument.WriteTo(xmlWriter);
                        xmlWriter.Close();
                    }
                }
                catch (Exception exception)
                {
                    // Show a message box to prove we were here
                    VsShellUtilities.ShowMessageBox(
                        FormatXmlCommand.serviceProvider,
                        exception.Message,
                        Resources.EditorExtensionsTitle,
                        OLEMSGICON.OLEMSGICON_CRITICAL,
                        OLEMSGBUTTON.OLEMSGBUTTON_OK,
                        OLEMSGDEFBUTTON.OLEMSGDEFBUTTON_FIRST);
                }

                // The result of beautifying a long string of XML is another long string that is scrubbed and beautified.  This string will be used
                // to replace the original content of the module.
                return(stringWriter.ToString());
            }
        }
        /// <summary>
        /// Sorts the attributes of an element and all it's children in alphabetical order.
        /// </summary>
        /// <param name="sourceNode">The original XElement.</param>
        /// <param name="targetContainer">The target XElement where the newly sorted node is placed.</param>
        private static void RecurseIntoDocument(XNode sourceNode, XContainer targetContainer)
        {
            // Convert the generic node to a specific type.
            XElement sourceElement = sourceNode as XElement;

            if (sourceElement != null)
            {
                // Arrange all the attributes in alphabetical order.
                SortedDictionary <string, XAttribute> sortedDictionary = new SortedDictionary <string, XAttribute>();
                foreach (XAttribute attribute in sourceElement.Attributes())
                {
                    sortedDictionary.Add(attribute.Name.LocalName, attribute);
                }

                // Create a new target element from the source and remove the existing attributes.  They'll be replaced with the ordered list.
                XElement element = new XElement(sourceElement);
                element.RemoveAll();

                // Replace the attributes in alphabetical order.
                foreach (KeyValuePair <string, XAttribute> keyValuePair in sortedDictionary)
                {
                    element.Add(keyValuePair.Value);
                }

                // Add it back to the target document.
                targetContainer.Add(element);

                // Recurse into each of the child elements.
                foreach (XNode childNode in sourceElement.Nodes())
                {
                    FormatXmlCommand.RecurseIntoDocument(childNode, element);
                }
            }
            else
            {
                // Pass all other nodes into the output without alterations.
                targetContainer.Add(sourceNode);
            }
        }