c# – Building a tree from a string

Question:

Good afternoon, Connoisseurs! Sharpe has only recently become involved (as well as programming in general). A task from a string like

{
{"SbCnts",
    {"12","Ученики","","","0","5","2","2","2","25","1","0","1","13","13","0","1","1",
        {"Params",
            {"4936","ПрибытиеОУ","Название ОУ, в которое прибыл, поступил","Название ОУ, в которое прибыл, поступил","","0"}
        },
        {"Form",
            {"13","ФормаСписка","",""}
        }
    },
    {"14","Уроки","","","12","5","2","2","2","25","1","0","1","15","15","0","1","1",
        {"Params"},
        {"Form",
            {"15","ФормаСписка","",""}
        }
    }
},
{"Registers"},
{"Documents"}
}

build element tree

public class Node
{
     public Node Parent;
     public string Value;
     public List<Node> SubNodes;
}

item delimiters are { and }

Please tell me the algorithm of actions or an example of code.

I try like this:

Node root = new Node { Parent = null, Value = "root", SubNodes = new List<Node>() };
Node node = root;
foreach (char c in data)
{
   switch (c)
   {
       case '{':node = new Node { Parent = node, Value = String.Empty, SubNodes = new List<Node>() };
                        node.Parent.SubNodes.Add(node);
                        break;
       case '}': node = new Node { Parent = node.Parent.Parent, Value = String.Empty, SubNodes = new List<Node>() };
                        if (node.Parent != null) node.Parent.SubNodes.Add(node);
                        break;
       default: node.Value += c;break;
   }
}

It turns out, but it's crooked … I'll make a reservation right away, a string is a piece of MetaDataStream from 1C 7.7

Answer:

Thanks to all! In principle, I got what I wanted.


using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
//https://github.com/Sicos1977/CompoundFileStorage
using CompoundFileStorage;

namespace OneC_Metadata_v2
{
    public class MetaDataReader
    {
        public class Node
        {
            public Node Parent;
            public string Value;
            public List Values;
            public List SubNodes;
            public override string ToString()
            {
                return Value;
            }
        }

        public List Enums { get; private set; }
        public List Catalogs { get; private set; }
        public List Constants { get; private set; }

        private static Node ReadContent(string data)
        {
            const string separator = "\",\"";
            var root = new Node { Parent = null, Value = "root", SubNodes = new List() };
            var node = root;

            for (var i = 0; i () };
                        node.Parent.SubNodes.Add(node);
                        break;
                    case '}':
                        var subs = node.Value.Split(new[] { separator }, StringSplitOptions.None).Select(x => x.Replace("\"", string.Empty).Trim()).ToList();
                        node.Values = subs;
                        node.Value = node.Value.Replace("\"", string.Empty);
                        node = node.Parent;
                        break;
                    default:
                        if (c == ',')
                        {
                            if (data[i + 1] != '{')
                            {
                                node.Value += c;
                            }
                        }
                        else
                        {
                            node.Value += c;
                        }
                        break;
                }
            }
            return root;
        }

        public enum DataBaseType { Dbf, Sql }

        public MetaDataReader(string dataBase)
        {
            var compoundFile = new CompoundFile(Path.Combine(dataBase, "1Cv7.MD"));
            var metadata = (CFStorage)compoundFile.RootStorage.Children.FirstOrDefault(n => n.Name == "Metadata");
            var mds = (CFStream)metadata?.Children.FirstOrDefault(n => n.Name == "Main MetaData Stream");
            if (mds == null) return;
            var data = mds.GetData();
            compoundFile.Close();
            var content = Encoding.Default.GetString(data).Replace("\r\n", string.Empty);
            var start = content.IndexOf('{');
            content = content.Substring(start);
            var root = ReadContent(content);
            var mdConstants = root.SubNodes[0].SubNodes.FirstOrDefault(n => n.Value == "Consts");
            Constants = LoadConstants(mdConstants);
            var mdEnums = root.SubNodes[0].SubNodes.FirstOrDefault(n => n.Value == "EnumList");
            Enums = LoadEnums(mdEnums);
            var mdCatalogs = root.SubNodes[0].SubNodes.FirstOrDefault(n => n.Value == "SbCnts");
            Catalogs = LoadCatalogs(mdCatalogs);
        }

        private static List LoadEnums(Node mdEnums)
        {
            var result = new List();
            foreach (var enumItem in mdEnums.SubNodes)
            {
                var e = new MdEnum()
                {
                    Id = int.Parse(enumItem.Values[0]),
                    Name = enumItem.Values[1],
                    Comment = enumItem.Values[2],
                    Synonym = enumItem.Values[3]
                };
                foreach (var enumValue in enumItem.SubNodes[0].SubNodes)
                {
                    e.Values.Add(new MdEnum.MdEnumValue()
                    {
                        Id = int.Parse(enumValue.Values[0]),
                        Name = enumValue.Values[1],
                        Comment = enumValue.Values[2],
                        Synonym = enumValue.Values[3],
                        Represent = enumValue.Values[4]
                    });
                }
                result.Add(e);
            }
            return result;
        }

        private static List LoadCatalogs(Node mdCatalogs)
        {
            var result = new List();
            foreach (var cItem in mdCatalogs.SubNodes)
            {
                var catalog = new MdCatalog()
                {
                    Id = int.Parse(cItem.Values[0]),
                    Name = cItem.Values[1],
                    Comment = cItem.Values[2],
                    Synonym = cItem.Values[3],
                    Parent = int.Parse(cItem.Values[4]),
                    CodeLength = int.Parse(cItem.Values[5]),
                    CodeSeries = int.Parse(cItem.Values[6]) == 1 ? CodeSeries.InЕheReference : CodeSeries.WithinSubmission,
                    CodeType = int.Parse(cItem.Values[7]) == 2 ? CodeType.Numeric : CodeType.Text,
                    AutomaticNumbering = int.Parse(cItem.Values[8]) == 2,
                    NameLength = int.Parse(cItem.Values[9]),
                    RepresentType = int.Parse(cItem.Values[10]) == 0 ? RepresentType.Code : RepresentType.Name,
                    LevelsCount = int.Parse(cItem.Values[12]),
                    UniqueControl = int.Parse(cItem.Values[16]) == 1,
                    TopGroups = int.Parse(cItem.Values[17]) == 1
                };
                foreach (var cField in cItem.SubNodes[0].SubNodes)
                {
                    catalog.Fields.Add(new MdCatalog.MdCatalogField()
                    {
                        Id = int.Parse(cField.Values[0]),
                        Name = cField.Values[1],
                        Comment = cField.Values[2],
                        Synonym = cField.Values[3],
                        Type = cField.Values[4],
                        Length = int.Parse(cField.Values[5]),
                        Accuracy = int.Parse(cField.Values[6]),
                        ParentTypeId = int.Parse(cField.Values[7])
                    });

                }
                result.Add(catalog);
            }
            return result;
        }

        private static List LoadConstants(Node mdConstants)
        {
            var result = new List();
            foreach (var item in mdConstants.SubNodes)
            {
                result.Add(new MdConstant()
                {
                    Id = int.Parse(item.Values[0]),
                    Name = item.Values[1],
                    Comment = item.Values[2],
                    Synonym = item.Values[3],
                    Type = item.Values[4],
                    Length = int.Parse(item.Values[5]),
                    Accuracy = int.Parse(item.Values[6]),
                    ParentTypeId = int.Parse(item.Values[7])
                });
            }
            return result;
        }
    }
}
Scroll to Top