private void CopyChildrens(TagItem copyTo, TagItem copyFrom) { TagItem copyToChild; foreach (TagItem item in copyFrom.Childrens) { switch (item.Type) { case "None": copyToChild = copyTo.AddChild(item.Name, null); break; case "Bool": copyToChild = copyTo.AddChild(item.Name, (bool)item.Value); break; case "Int": copyToChild = copyTo.AddChild(item.Name, (int)item.Value); break; case "Double": copyToChild = copyTo.AddChild(item.Name, (double)item.Value); break; default: throw new Exception("Неизвестный тип."); } CopyChildrens(copyToChild, item); } }
//Показывает окно на добавление тега. Если все данные введены и есть поддтверждение, //то новый элемент добавляется как дочерний элемент к целевому элементу private void AskUserToAddTag(TagItem target) { AddNewTagWindow confirmAdding = new AddNewTagWindow(this); if (confirmAdding.ShowDialog() == true) { if (confirmAdding.TextBoxValue.Length <= 0) { MessageBox.Show("Задано пустое имя.", "Ошибка"); } else if (!target.IsChildNameUnique(confirmAdding.TextBoxValue)) { MessageBox.Show("Такое имя уже есть среди детей родителя этого элемента.", "Ошибка"); } else if (Regex.IsMatch(confirmAdding.TextBoxValue, "[^a-zA-Zа-яА-Я0-9]")) { MessageBox.Show("Найдены недопустимые символы. Используйте только алфавиты кириллицы и латиницы, а так же цифры", "Ошибка"); } else { isUnsavedData = true; switch (confirmAdding.SelectedType) { case "None": target.AddChild(confirmAdding.TextBoxValue, null); break; case "Bool": target.AddChild(confirmAdding.TextBoxValue, false); break; case "Int": target.AddChild(confirmAdding.TextBoxValue, 0); break; case "Double": target.AddChild(confirmAdding.TextBoxValue, 0.0); break; } } } }
//Открывает XML файл и создает структуру из содержимого public bool LoadStructureFromFile(string filepath) { StreamReader reader; try { reader = new StreamReader(filepath); } catch { return(false); } Regex tagRegEx = new Regex("(<tag[^>]*>|</tag>)"); Regex nameRegEx = new Regex("(?<=name=\")\\w+(?=\")"); Regex valueRegEx = new Regex("(?<=value=\")((\\d+(,\\d+)?)|True|False|None)(?=\")"); Regex typeRegEx = new Regex("(?<=type=\")(None|Bool|Int|Double)(?=\")"); //Добавление новых элементов происходит относительно этого указателся TagItem cursor = Root; //Находим все открывающие и закрывающие теги string rawData = reader.ReadToEnd(); reader.Close(); MatchCollection allTags = tagRegEx.Matches(rawData); //Проверяем валидность файла if (allTags.Count == 0) { throw new Exception("Неверный формат файла. Отсутствует структура"); } if (allTags[0].Value != "<tag name=\"Root\" type=\"None\">") { throw new Exception("Неверный формат файла. Все содержимое должно находится в теге Root"); } //Открывающий тег = +1; Закрывающий = -1; //значение ушло в минус, то закрывающих слишком много //после окончания цикла оно не ноль - то открывающих много int openCloseTagsCheck = 1; foreach (Match hit in allTags) { if (openCloseTagsCheck <= 0) { throw new Exception("Неверный формат файла. Некоторые теги не находятся внутри Элемента Root"); } if (hit.Value == "</tag>") { openCloseTagsCheck--; } else if (hit != allTags[0]) { openCloseTagsCheck++; } } if (openCloseTagsCheck > 0) { throw new Exception("Неверный формат файла. Открывающих тегов больше чем закрывающих"); } TagRoot.Childrens.Clear(); //Обрабатываем теги по порядку foreach (Match hit in allTags) { //Если тег закрывающий то это значит мы закончили добавлять детей в элемент структуры, на который ссылается указатель //указателем становится родитель этого элемета(движение вверх по дереву) if (hit.Value == "</tag>") { cursor = cursor.Parent; } //Обрабатываем все теги кроме тега Root else if (hit.Value != "<tag name=\"Root\" type=\"None\">") { //Верезаем значения из открывающего тега string name = nameRegEx.Match(hit.Value).Value; string value = valueRegEx.Match(hit.Value).Value; string type = typeRegEx.Match(hit.Value).Value; if (name.Length == 0) { throw new Exception("Имя тега не указано"); } //В зависимости от типа добавляем новый элемент //и указатель ссылается на этот элемент switch (type) { case "None": cursor = cursor.AddChild(name, null); break; case "Bool": cursor = cursor.AddChild(name, bool.Parse(value)); break; case "Int": cursor = cursor.AddChild(name, int.Parse(value)); break; case "Double": cursor = cursor.AddChild(name, double.Parse(value)); break; default: throw new Exception("Неизвестный тип."); } } } return(true); }