private static bool ParseRibbonXml(string[] inputFiles, Hashtable pairs, Hashtable pairsNonLoc, Type t, string xpath, string KEY_FORMAT, out HashSet ids, out Hashtable values)
        {
            // Add to the proptable
            Hashtable propTable = new Hashtable();
            foreach (PropertyInfo prop in t.GetProperties(BindingFlags.Public | BindingFlags.Instance))
            {
                propTable.Add(prop.Name, prop);
            }

            ids = new HashSet();
            values = new Hashtable();

            foreach (string relativeInputFile in inputFiles)
            {
                string inputFile = Path.GetFullPath(relativeInputFile);
                try
                {
                    if (!File.Exists(inputFile))
                        throw new ConfigurationErrorsException("File not found");

                    XmlNamespaceManager nsm = new XmlNamespaceManager(new NameTable());
                    nsm.AddNamespace(RibbonMarkup.XPathPrefix, RibbonMarkup.NamespaceUri);

                    XmlDocument xmlDoc = new XmlDocument();
                    xmlDoc.Load(inputFile);

                    foreach (XmlElement el in xmlDoc.SelectNodes(xpath, nsm))
                    {

                        string id = el.GetAttribute("Id");
                        string symbol = el.GetAttribute("Symbol");
                        if (id == "")
                            throw new ConfigurationErrorsException(
                                string.Format(CultureInfo.CurrentCulture, "The following command is missing an identifier:\r\n{0}", el.OuterXml));

                        // RibbonDUI.js requires that command names begin with the prefix "cmd".
                        // We will strip that prefix when generating the CommandId enum.
                        int cmdIndex = symbol.IndexOf("cmd");
                        if (cmdIndex >= 0)
                        {
                            symbol = symbol.Substring(cmdIndex + 3);
                        }

                        if (!ids.Add(symbol))
                            throw new ConfigurationErrorsException("Duplicate command: " + symbol + " with id " + id);
                        values.Add(symbol, id);

                        foreach (XmlAttribute attr in el.Attributes)
                        {
                            if (attr.NamespaceURI.Length != 0)
                                continue;

                            string name = attr.Name;

                            object val;
                            PropertyInfo thisProp = propTable[name] as PropertyInfo;
                            if (thisProp == null)
                                continue; // This attribute does not have a corresponding property in the type.

                            if (thisProp.PropertyType.IsPrimitive)
                            {
                                try
                                {
                                    val = Convert.ChangeType(attr.Value, thisProp.PropertyType).ToString();
                                }
                                catch (ArgumentException)
                                {
                                    throw new ConfigurationErrorsException(string.Format(CultureInfo.InvariantCulture, "Invalid attribute value: {0}=\"{1}\"", attr.Name, attr.Value));
                                }
                            }
                            else if (thisProp.PropertyType == typeof(string))
                            {
                                val = attr.Value;
                            }
                            else
                            {
                                throw new ConfigurationErrorsException("Unexpected attribute: " + attr.Name);
                            }

                            string comment = GetComment(el, name);

                            object[] locAttr = thisProp.GetCustomAttributes(typeof(LocalizableAttribute), true);
                            bool isNonLoc = locAttr.Length == 0 || !((LocalizableAttribute)locAttr[0]).IsLocalizable;
                            if (isNonLoc)
                                pairsNonLoc.Add(string.Format(CultureInfo.InvariantCulture, KEY_FORMAT, symbol, name), new Values(val, comment));
                            else
                                pairs.Add(string.Format(CultureInfo.InvariantCulture, KEY_FORMAT, symbol, name), new Values(val, comment));
                        }
                    }
                }
                catch (ConfigurationErrorsException ce)
                {
                    Console.Error.WriteLine(string.Format(CultureInfo.InvariantCulture, "Error in file {0}: {1}", inputFile, ce.Message));
                    return false;
                }
            }

            return true;
        }
        private static bool ParseCommandXml(string[] inputFiles, Hashtable pairs, Hashtable pairsNonLoc, Type t, string xpath, string KEY_FORMAT, out HashSet ids)
        {
            bool seenMenu = false;

            Hashtable propTable = new Hashtable();
            foreach (PropertyInfo prop in t.GetProperties(BindingFlags.Public | BindingFlags.Instance))
            {
                propTable.Add(prop.Name, prop);
            }

            ids = new HashSet();

            foreach (string relativeInputFile in inputFiles)
            {
                string inputFile = Path.GetFullPath(relativeInputFile);
                try
                {
                    if (!File.Exists(inputFile))
                        throw new ConfigurationErrorsException("File not found");

                    XmlDocument xmlDoc = new XmlDocument();
                    xmlDoc.Load(inputFile);
                    foreach (XmlElement el in xmlDoc.SelectNodes(xpath))
                    {
                        string id = el.GetAttribute("Identifier");
                        if (id == "")
                            throw new ConfigurationErrorsException(
                                String.Format(CultureInfo.CurrentCulture, "The following command is missing an identifier:\r\n{0}", el.OuterXml));

                        if (!ids.Add(id))
                            throw new ConfigurationErrorsException("Duplicate command identifier: " + id);

                        foreach (XmlAttribute attr in el.Attributes)
                        {
                            if (attr.NamespaceURI.Length != 0)
                                continue;

                            string name = attr.Name;

                            if (name == "DebugOnly" || name == "Identifier")
                                continue;

                            object val;
                            PropertyInfo thisProp = propTable[name] as PropertyInfo;
                            if (thisProp == null)
                                throw new ConfigurationErrorsException(string.Format(CultureInfo.CurrentCulture, "Attribute {0} does not have a corresponding property", name));

                            if (thisProp.PropertyType.IsEnum)
                            {
                                try
                                {
                                    val = Enum.Parse(thisProp.PropertyType, attr.Value, false).ToString();
                                }
                                catch (ArgumentException)
                                {
                                    throw new ConfigurationErrorsException(string.Format(CultureInfo.InvariantCulture, "Invalid attribute value: {0}=\"{1}\"", attr.Name, attr.Value));
                                }
                            }
                            else if (thisProp.PropertyType.IsPrimitive)
                            {
                                try
                                {
                                    val = Convert.ChangeType(attr.Value, thisProp.PropertyType).ToString();
                                }
                                catch (ArgumentException)
                                {
                                    throw new ConfigurationErrorsException(string.Format(CultureInfo.InvariantCulture, "Invalid attribute value: {0}=\"{1}\"", attr.Name, attr.Value));
                                }
                            }
                            else if (thisProp.PropertyType == typeof(string))
                            {
                                val = attr.Value;
                            }
                            else
                            {
                                throw new ConfigurationErrorsException("Unexpected attribute: " + attr.Name);
                            }

                            string comment = GetComment(el, name);

                            object[] locAttr = thisProp.GetCustomAttributes(typeof(LocalizableAttribute), true);
                            bool isNonLoc = locAttr.Length == 0 || !((LocalizableAttribute)locAttr[0]).IsLocalizable;
                            if (isNonLoc)
                                pairsNonLoc.Add(string.Format(CultureInfo.InvariantCulture, KEY_FORMAT, id, name), new Values(val, comment));
                            else
                                pairs.Add(string.Format(CultureInfo.InvariantCulture, KEY_FORMAT, id, name), new Values(val, comment));
                        }
                    }

                    foreach (XmlElement mainMenuEl in xmlDoc.SelectNodes("/Commands/MainMenu"))
                    {
                        if (seenMenu)
                            throw new ConfigurationErrorsException("Duplicate main menu definition detected");
                        seenMenu = true;

                        Console.WriteLine("Parsing main menu definition");
                        StringBuilder menuStructure = new StringBuilder();
                        BuildMenuString(menuStructure, mainMenuEl, ids, pairs);
                        pairsNonLoc.Add("MainMenuStructure", new Values(menuStructure.ToString(), ""));
                    }
                }
                catch (ConfigurationErrorsException ce)
                {
                    Console.Error.WriteLine(string.Format(CultureInfo.InvariantCulture, "Error in file {0}: {1}", inputFile, ce.Message));
                    return false;
                }
            }

            return true;
        }
        protected BlogPost[] GetRecentPostsInternal(string blogId, int maxPosts, bool includeCategories, DateTime? now)
        {
            Login();

            FixupBlogId(ref blogId);

            HashSet seenIds = new HashSet();

            ArrayList blogPosts = new ArrayList();
            try
            {
                while (true)
                {
                    XmlDocument doc;
                    Uri thisUri = new Uri(blogId);

                    // This while-loop nonsense is necessary because New Blogger has a bug
                    // where the official URL for getting recent posts doesn't work when
                    // the orderby=published flag is set, but there's an un-official URL
                    // that will work correctly. Therefore, subclasses need the ability
                    // to inspect exceptions that occur, along with the URI that was used
                    // to make the request, and determine whether an alternate URI should
                    // be used.
                    while (true)
                    {
                        try
                        {
                            doc = xmlRestRequestHelper.Get(ref thisUri, RequestFilter);
                            break;
                        }
                        catch (Exception e)
                        {
                            Trace.WriteLine(e.ToString());
                            if (AttemptAlternateGetRecentPostUrl(e, ref blogId))
                                continue;
                            else
                                throw;
                        }
                    }

                    XmlNodeList nodeList = doc.SelectNodes("/atom:feed/atom:entry", _nsMgr);
                    if (nodeList.Count == 0)
                        break;
                    foreach (XmlElement node in nodeList)
                    {
                        BlogPost blogPost = this.Parse(node, includeCategories, thisUri);
                        if (blogPost != null)
                        {
                            if (seenIds.Contains(blogPost.Id))
                                throw new DuplicateEntryIdException();
                            seenIds.Add(blogPost.Id);

                            if (!now.HasValue || blogPost.DatePublished.CompareTo(now.Value) < 0)
                                blogPosts.Add(blogPost);
                        }
                        if (blogPosts.Count >= maxPosts)
                            break;
                    }
                    if (blogPosts.Count >= maxPosts)
                        break;

                    XmlElement nextNode = doc.SelectSingleNode("/atom:feed/atom:link[@rel='next']", _nsMgr) as XmlElement;
                    if (nextNode == null)
                        break;
                    blogId = XmlHelper.GetUrl(nextNode, "@href", thisUri);
                    if (blogId.Length == 0)
                        break;
                }
            }
            catch (DuplicateEntryIdException)
            {

                if (ApplicationDiagnostics.AutomationMode)
                    Trace.WriteLine("Duplicate IDs detected in feed");
                else
                    Trace.Fail("Duplicate IDs detected in feed");
            }
            return (BlogPost[])blogPosts.ToArray(typeof(BlogPost));
        }