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