/// <summary> Creates a new instance of the crash report context from the specified file. </summary> public static FGenericCrashContext FromFile(string Filepath) { // The crash report context contains invalid characters, we need to fix them all in order to parse the XML. HashSet <string> TagsToIgnore = new HashSet <string>() { "<FGenericCrashContext>", "<RuntimeProperties>", "<PlatformProperties>", "</FGenericCrashContext>", "</RuntimeProperties>", "</PlatformProperties>" }; string[] XMLText = File.ReadAllLines(Filepath); string CopyText = string.Join(Environment.NewLine, XMLText); string NodeOpen = ""; string NodeEnd = ""; List <string> Multiline = new List <string>(); List <int> MultiIndex = new List <int>(); int OpenEnd = 0; int EndStart = 0; for (int LineIndex = 1; LineIndex < XMLText.Length; LineIndex++) { string XMLLine = XMLText[LineIndex].Replace("\t", ""); bool bIgnore = TagsToIgnore.Contains(XMLLine); if (bIgnore) { continue; } // XML node without data, skip. if (XMLLine.Contains("/>")) { continue; } if (NodeOpen == "") { // Parse the tag. //<Version>"1"</Version> //<Version /> int OpenStart = XMLLine.IndexOf('<'); OpenEnd = XMLLine.IndexOf('>', OpenStart); NodeOpen = XMLLine.Substring(OpenStart + 1, OpenEnd - OpenStart - 1); } EndStart = XMLLine.IndexOf("</"); int EndEnd = 0; if (EndStart != -1) { EndEnd = XMLLine.IndexOf('>', EndStart); NodeEnd = XMLLine.Substring(EndStart + 2, EndEnd - EndStart - 2); } else { Multiline.Add(XMLLine.Substring(OpenEnd != 0 ? OpenEnd + 1 : 0)); MultiIndex.Add(LineIndex); OpenEnd = 0; } // Valid tag, fix invalid characters. if (NodeOpen == NodeEnd) { if (Multiline.Count == 0) { string NodeValue = XMLLine.Substring(OpenEnd + 1, EndStart - OpenEnd - 1); string EscapedXMLText = EscapeXMLString(UnescapeXMLString(NodeValue)); // Required for support old and new type format. XMLText[LineIndex] = string.Format("<{0}>{1}</{0}>", NodeOpen, EscapedXMLText); } else { Multiline.Add(XMLLine.Substring(0, EndStart)); MultiIndex.Add(LineIndex); for (int Inner = 0; Inner < Multiline.Count; Inner++) { string EscapedXMLText = EscapeXMLString(UnescapeXMLString(Multiline[Inner])); if (Inner == 0) { XMLText[MultiIndex[Inner]] = string.Format("<{0}>{1}", NodeOpen, EscapedXMLText); } else if (Inner == Multiline.Count - 1) { XMLText[MultiIndex[Inner]] = string.Format("{1}</{0}>", NodeOpen, EscapedXMLText); } else { XMLText[MultiIndex[Inner]] = EscapedXMLText; } } Multiline.Clear(); MultiIndex.Clear(); } NodeOpen = NodeEnd = ""; } } string XMLTextJoined = string.Join(Environment.NewLine, XMLText); FGenericCrashContext Context = XmlHandler.FromXmlString <FGenericCrashContext>(XMLTextJoined); if (Context.UntypedXMLNodes != null) { var Typed = ((IEnumerable)Context.UntypedXMLNodes) .Cast <XmlNode>() .Select(X => new KeyValuePair <string, string>(X.Name, X.InnerText)) .ToList(); } return(Context); }
/// <summary> Writes this instance of the crash report context to the specified file. </summary> public void ToFile() { XmlHandler.WriteXml <FGenericCrashContext>(this, Path.Combine(CrashDirectory, FGenericCrashContext.CrashContextRuntimeXMLName)); }