/// <summary> /// Sets values of this class with values from given XML file. /// </summary> /// <param name="ConfigurationXmlPath">The path to the file with values.</param> private static void LoadDataFromFile(string ConfigurationXmlPath) { XmlDocument ConfigDocument = new XmlDocument(); XmlNamespaceManager NS = new XmlNamespaceManager(ConfigDocument.NameTable); NS.AddNamespace("ns", "https://www.unrealengine.com/BuildConfiguration"); XmlReaderSettings ReaderSettings = new XmlReaderSettings(); ReaderSettings.ValidationEventHandler += (object Sender, System.Xml.Schema.ValidationEventArgs EventArgs) => { throw new BuildException("XmlConfigLoader: Reading config XML failed:\n{0}({1}): {2}", ConfigurationXmlPath, EventArgs.Exception.LineNumber, EventArgs.Message); }; ReaderSettings.ValidationType = ValidationType.Schema; ReaderSettings.Schemas.Add(GetConfigSchema()); using (StringReader SR = new StringReader(File.ReadAllText(ConfigurationXmlPath, Encoding.UTF8))) { XmlReader Reader = XmlReader.Create(SR, ReaderSettings); ConfigDocument.Load(Reader); } XmlNodeList XmlClasses = ConfigDocument.DocumentElement.SelectNodes("/ns:Configuration/*", NS); if (XmlClasses.Count == 0) { if (ConfigDocument.DocumentElement.Name == "Configuration") { ConfigDocument.DocumentElement.SetAttribute("xmlns", "https://www.unrealengine.com/BuildConfiguration"); XmlDocument NSDoc = new XmlDocument(); NSDoc.LoadXml(ConfigDocument.OuterXml); try { File.WriteAllText(ConfigurationXmlPath, WriteToBuffer(NSDoc)); } catch (Exception) { // Ignore gently. } XmlClasses = NSDoc.DocumentElement.SelectNodes("/ns:Configuration/*", NS); } } foreach (XmlNode XmlClass in XmlClasses) { Type ClassType = Type.GetType("UnrealBuildTool." + XmlClass.Name); if (ClassType == null) { Log.TraceVerbose("XmlConfig Loading: class '{0}' doesn't exist.", XmlClass.Name); continue; } if (!IsConfigurableClass(ClassType)) { Log.TraceVerbose("XmlConfig Loading: class '{0}' is not allowed to be configured using XML system.", XmlClass.Name); continue; } XmlConfigLoaderClassData ClassData; if (!Data.TryGetValue(ClassType, out ClassData)) { ClassData = new XmlConfigLoaderClassData(); Data.Add(ClassType, ClassData); } XmlNodeList XmlFields = XmlClass.SelectNodes("*"); foreach (XmlNode XmlField in XmlFields) { FieldInfo Field = ClassType.GetField(XmlField.Name); // allow settings in the .xml that don't exist, as another branch may have it, and can share this file from Documents if (Field == null) { PropertyInfo Property = ClassType.GetProperty(XmlField.Name); if (Property != null) { if (!IsConfigurable(Property)) { throw new BuildException("BuildConfiguration Loading: property '{0}' is either non-public, non-static or not-xml-configurable.", XmlField.Name); } ClassData.SetValue(Property, ParseFieldData(Property.PropertyType, XmlField.InnerText)); } continue; } if (!IsConfigurableField(Field)) { throw new BuildException("BuildConfiguration Loading: field '{0}' is either non-public, non-static or not-xml-configurable.", XmlField.Name); } if (Field.FieldType.IsArray) { // If the type is an array type get items for it. XmlNodeList XmlItems = XmlField.SelectNodes("ns:Item", NS); // Get the C# type of the array. Type ItemType = Field.FieldType.GetElementType(); // Create the array according to the ItemType. Array OutputArray = Array.CreateInstance(ItemType, XmlItems.Count); int Id = 0; foreach (XmlNode XmlItem in XmlItems) { // Append values to the OutputArray. OutputArray.SetValue(ParseFieldData(ItemType, XmlItem.InnerText), Id++); } ClassData.SetValue(Field, OutputArray); } else { ClassData.SetValue(Field, ParseFieldData(Field.FieldType, XmlField.InnerText)); } } } }
/// <summary> /// Sets values of this class with values from given XML file. /// </summary> /// <param name="ConfigurationXmlPath">The path to the file with values.</param> private static void Load(string ConfigurationXmlPath) { var ConfigDocument = new XmlDocument(); var NS = new XmlNamespaceManager(ConfigDocument.NameTable); NS.AddNamespace("ns", "https://www.unrealengine.com/BuildConfiguration"); ConfigDocument.Load(ConfigurationXmlPath); var XmlClasses = ConfigDocument.DocumentElement.SelectNodes("/ns:Configuration/*", NS); if (XmlClasses.Count == 0) { if (ConfigDocument.DocumentElement.Name == "Configuration") { ConfigDocument.DocumentElement.SetAttribute("xmlns", "https://www.unrealengine.com/BuildConfiguration"); var NSDoc = new XmlDocument(); NSDoc.LoadXml(ConfigDocument.OuterXml); try { File.WriteAllText(ConfigurationXmlPath, WriteToBuffer(NSDoc)); } catch (Exception) { // Ignore gently. } XmlClasses = NSDoc.DocumentElement.SelectNodes("/ns:Configuration/*", NS); } } foreach (XmlNode XmlClass in XmlClasses) { var ClassType = Type.GetType("UnrealBuildTool." + XmlClass.Name); if (ClassType == null) { Log.TraceVerbose("XmlConfig Loading: class '{0}' doesn't exist.", XmlClass.Name); continue; } if (!IsConfigurableClass(ClassType)) { Log.TraceVerbose("XmlConfig Loading: class '{0}' is not allowed to be configured using XML system.", XmlClass.Name); continue; } XmlConfigLoaderClassData ClassData; if (!Data.TryGetValue(ClassType, out ClassData)) { ClassData = new XmlConfigLoaderClassData(ClassType); Data.Add(ClassType, ClassData); } var XmlFields = XmlClass.SelectNodes("*"); foreach (XmlNode XmlField in XmlFields) { FieldInfo Field = ClassType.GetField(XmlField.Name); // allow settings in the .xml that don't exist, as another branch may have it, and can share this file from Documents if (Field == null) { continue; } if (!IsConfigurableField(Field)) { throw new BuildException("BuildConfiguration Loading: field '{0}' is either non-public, non-static or not-xml-configurable.", XmlField.Name); } if (Field.FieldType.IsArray) { // If the type is an array type get items for it. var XmlItems = XmlField.SelectNodes("ns:Item", NS); // Get the C# type of the array. var ItemType = Field.FieldType.GetElementType(); // Create the array according to the ItemType. var OutputArray = Array.CreateInstance(ItemType, XmlItems.Count); int Id = 0; foreach (XmlNode XmlItem in XmlItems) { // Append values to the OutputArray. OutputArray.SetValue(ParseFieldData(ItemType, XmlItem.InnerText), Id++); } ClassData.SetValue(Field, OutputArray); } else { ClassData.SetValue(Field, ParseFieldData(Field.FieldType, XmlField.InnerText)); } } } }