public static ParserEnumFile LoadFile(string path)
        {
            using (var input = File.OpenRead(path))
            {
                var doc = new XPathDocument(input);
                var nav = doc.CreateNavigator();

                var schema = new ParserEnumFile();

                var root = nav.SelectSingleNode("/enum");
                if (root == null)
                {
                    throw new InvalidOperationException();
                }

                schema.Name = root.GetAttribute("name", "");

                var table = root.SelectSingleNode("elements");
                schema.Enum = LoadEnumeration(table);

                return(schema);
            }
        }
        private static ParserSchema.Table LoadTable(XPathNavigator nav)
        {
            var table = new ParserSchema.Table();

            var columnIterator = nav.Select("column");

            while (columnIterator.MoveNext() == true)
            {
                var columnNode = columnIterator.Current;
                if (columnNode == null)
                {
                    throw new InvalidOperationException();
                }

                // ReSharper disable UseObjectOrCollectionInitializer
                var column = new ParserSchema.Column();
                // ReSharper restore UseObjectOrCollectionInitializer
                column.Name = columnNode.GetAttribute("name", "");

                var type  = columnNode.GetAttribute("type", "");
                var token = Parser.GlobalTokens.MatchToken(type, out column.Token, out column.Flags);

                var flagIterator = columnNode.Select("flags/flag");
                while (flagIterator.MoveNext() == true)
                {
                    if (flagIterator.Current == null)
                    {
                        throw new InvalidOperationException();
                    }

                    var flag = flagIterator.Current.Value;
                    if (Enum.IsDefined(typeof(Parser.ColumnFlags), flag) == false)
                    {
                        throw new FormatException("invalid schema flag");
                    }

                    column.Flags |= (Parser.ColumnFlags)Enum.Parse(typeof(Parser.ColumnFlags), flag);
                }

                column.Offset = (uint)GetIntElement(columnNode, "offset", 0);

                column.RedundantName = GetStringElement(columnNode, "redundant_name", null);

                column.MinBits       = (byte)GetIntElement(columnNode, "min_bits", 0);
                column.FloatRounding = GetStringElement(columnNode, "float_rounding", null);

                column.NumberOfElements = GetIntElement(columnNode, "num_elements", 0);
                column.Default          = GetIntElement(columnNode, "default", 0);
                column.StringLength     = GetIntElement(columnNode, "string_length", 0);
                column.DefaultString    = GetStringElement(columnNode, "default_string", null);
                column.CommandString    = GetStringElement(columnNode, "command_string", null);
                column.Size             = GetIntElement(columnNode, "size", 0);
                column.BitOffset        = GetIntElement(columnNode, "bit_offset", 0);

                var subtable = columnNode.SelectSingleNode("subtable");
                if (subtable != null)
                {
                    column.SubtableExternalName = subtable.GetAttribute("external", "");
                    column.SubtableIsExternal   = true;

                    var subtableTable = subtable.SelectSingleNode("table");
                    if (subtableTable != null)
                    {
                        column.SubtableIsExternal = false;
                        column.Subtable           = LoadTable(subtableTable);
                    }
                }

                var staticDefineList = columnNode.SelectSingleNode("static_define_list");
                if (staticDefineList != null)
                {
                    column.StaticDefineListExternalName = staticDefineList.GetAttribute("external", "");
                    column.StaticDefineListIsExternal   = true;

                    var staticDefineListElements = staticDefineList.SelectSingleNode("elements");
                    if (staticDefineListElements != null)
                    {
                        column.StaticDefineListIsExternal = false;
                        column.StaticDefineList           = ParserEnumFile.LoadEnumeration(staticDefineListElements);
                    }
                }

                var formatName = GetStringElement(columnNode, "format", null);
                if (string.IsNullOrEmpty(formatName) == false)
                {
                    ParserSchema.ColumnFormat format;
                    if (Enum.TryParse(formatName, true, out format) == false)
                    {
                        throw new FormatException("invalid column format");
                    }
                    column.Format = format;
                }

                var formatStringIterator = columnNode.Select("format_strings/format_string");
                column.FormatStrings.Clear();
                while (formatStringIterator.MoveNext() == true)
                {
                    var formatStringNode = formatStringIterator.Current;
                    if (formatStringNode == null)
                    {
                        throw new InvalidOperationException();
                    }

                    var formatStringKey = formatStringNode.GetAttribute("name", "");
                    if (string.IsNullOrEmpty(formatStringKey) == true)
                    {
                        throw new FormatException("invalid schema format string key");
                    }

                    /*Console.WriteLine("Adding {0}={1} to {2}",
                     *  formatStringKey, formatStringNode.Value, column.Name);*/
                    column.FormatStrings.Add(formatStringKey, formatStringNode.Value);
                }

                table.Columns.Add(column);
            }

            return(table);
        }