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)); }