/// <summary> /// создание итема в списке для невалидной книги /// </summary> private void createNotValidateBookItem(string FilePath, FB2UnionGenres fb2g, FB2Validator fv2Validator, SharpZipLibWorker sharpZipLib) { if (File.Exists(FilePath)) { string TempDir = Settings.Settings.TempDirPath; string FileExt = Path.GetExtension(FilePath); ListViewItem.ListViewSubItem[] subItems; if (FilesWorker.isFB2File(FilePath) || FilesWorker.isFB2Archive(FilePath)) { ListViewItem item = new ListViewItem(FilePath, FilesWorker.isFB2File(FilePath) ? 1 : 2); try { if (FilesWorker.isFB2File(FilePath)) { item.ForeColor = Colors.FB2ForeColor; subItems = createSubItemsWithMetaData(FilePath, FileExt, item, ref fb2g, ref fv2Validator); } else { // для zip-архивов FilesWorker.RemoveDir(TempDir); sharpZipLib.UnZipFB2Files(FilePath, TempDir); string [] files = Directory.GetFiles(TempDir); if (FilesWorker.isFB2File(files[0])) { item.ForeColor = Colors.ZipFB2ForeColor; subItems = createSubItemsWithMetaData(files[0], FileExt, item, ref fb2g, ref fv2Validator); } else { item.ForeColor = Colors.BadZipForeColor; subItems = WorksWithBooks.createEmptySubItemsForItem(item); } } if (subItems != null) { item.SubItems.AddRange(subItems); } } catch (Exception ex) { Debug.DebugMessage( null, ex, "FB2NotValidateForm.createNotValidateBookItem(): Создание итема в списке для невалидной книги." ); subItems = WorksWithBooks.createEmptySubItemsForItem(item); if (subItems != null) { item.SubItems.AddRange(subItems); item.ForeColor = Colors.BadZipForeColor; } } item.Tag = new ListViewItemType("f", FilePath); item.BackColor = Colors.FileBackColor; if (subItems != null) { m_listViewFB2Files.Items.Add(item); } } } }
// Проверяем - это отмена, ошибка, или конец задачи и сообщить private void bw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) { // очистка временной папки FilesWorker.RemoveDir(m_TempDir); if (m_autoResizeColumns) { MiscListView.AutoResizeColumns(m_listView); } DateTime dtEnd = DateTime.Now; string sTime = dtEnd.Subtract(m_dtStart).ToString() + " (час.:мин.:сек.)"; if (e.Cancelled) { m_EndMode.EndMode = EndWorkModeEnum.Cancelled; m_EndMode.Message = "Отображение метаданных книг прервано!\nСгенерирован список " + ProgressBar.Value + " каталогов и папок из " + ProgressBar.Maximum + "\nЗатрачено времени: " + sTime; } else if (e.Error != null) { m_EndMode.EndMode = EndWorkModeEnum.Error; m_EndMode.Message = "Ошибка:\n" + e.Error.Message + "\n" + e.Error.StackTrace + "\nСгенерирован список " + ProgressBar.Value + " каталогов и папок из " + ProgressBar.Maximum + "\nЗатрачено времени: " + sTime; } else { m_EndMode.EndMode = EndWorkModeEnum.Done; m_EndMode.Message = "Отображение метаданных книг завершено!\nЗатрачено времени: " + sTime; } this.Close(); }
// Проверяем - это отмена, ошибка, или конец задачи и сообщить private void bw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) { DateTime dtEnd = DateTime.Now; FilesWorker.RemoveDir(Settings.Settings.TempDirPath); string sTime = dtEnd.Subtract(m_dtStart).ToString().Substring(0, 8) + " (час.:мин.:сек.)"; if (e.Cancelled) { m_EndMode.EndMode = EndWorkModeEnum.Cancelled; if (m_StopToSave) { // остановка поиска копий с сохранением списка необработанных книг в файл m_StopToSave = false; // сохранение в xml-файл списка данных о невалидных и необработанных книг sfdList.Title = "Укажите файл для будущего возобновления поиска всех невалидных книг:"; sfdList.Filter = "SharpFBTools Файлы хода работы Корректора (*.corr_break)|*.corr_break"; sfdList.FileName = string.Empty; sfdList.InitialDirectory = Settings.Settings.ProgDir; DialogResult result = sfdList.ShowDialog(); if (result == DialogResult.OK) { ControlPanel.Enabled = false; StatusLabel.Text += "Сохранение данных анализа в файл:\r"; StatusLabel.Text += sfdList.FileName; saveSearchedDataToXmlFile(sfdList.FileName, ref m_FilesList); m_EndMode.Message = "Поиск всех невалидных fb2 файлов прерван!\nДанные поиска и список оставшихся для обработки книг сохранены в xml-файл:\n\n" + sfdList.FileName + "\n\nЗатрачено времени: " + sTime; } } else { // остановка поиска без сохранения результата работы в xml-файл m_EndMode.Message = "Поиск всех невалидных fb2-файлов остановлен!\nСписок невалидных fb2-файлов не сформирован полностью!\nЗатрачено времени: " + sTime; } } else if (e.Error != null) { m_EndMode.EndMode = EndWorkModeEnum.Error; m_EndMode.Message = "Ошибка:\n" + e.Error.Message + "\n" + e.Error.StackTrace + "\nЗатрачено времени: " + sTime; } else { m_EndMode.EndMode = EndWorkModeEnum.Done; m_EndMode.Message = "Поиск всех невалидных fb2-файлов завершен!\nЗатрачено времени: " + sTime; if (m_listViewFB2Files.Items.Count == 0) { m_EndMode.Message += "\n\nНе найдено НИ ОДНОЙ невалидной книги!"; } } m_FilesList.Clear(); this.Close(); }
/// <summary> /// Валидация fb2, fb2.zip ли fbz файлов по пути FilePath /// </summary> /// <returns>Пустая строка, файл валиден; Строка с сообщением, если файл невалиден</returns> public string ValidatingFB2File(string FilePath) { bool IsZip = false; string Result = validate(FilePath, Settings.Settings.SchemePath, ref IsZip); if (IsZip) // удаляем временные файлы только, если проверяли архив { FilesWorker.RemoveDir(_TempDir); } return(Result); }
/// <summary> /// Формирование представления Групп с их книгами /// </summary> private void makeBookCopiesView(FB2FilesDataInGroup fb2BookList, ListView listViewFB2Files, ref StatusView sv) { Hashtable htBookGroups = new Hashtable(new FB2CultureComparer()); // хеш-таблица групп одинаковых книг ListViewGroup lvGroup = null; // группа одинаковых книг string Valid = string.Empty; foreach (BookData bd in fb2BookList) { ++sv.AllFB2InGroups; // число книг во всех группах одинаковых книг lvGroup = new ListViewGroup(fb2BookList.Group); ListViewItem lvi = new ListViewItem(bd.Path); if (FilesWorker.isFB2Archive(bd.Path)) { lvi.ForeColor = Colors.ZipFB2ForeColor; } lvi.SubItems.Add(MakeBookTitleString(bd.BookTitle)); lvi.SubItems.Add(MakeAuthorsString(bd.Authors)); lvi.SubItems.Add(MakeGenresString(bd.Genres)); lvi.SubItems.Add(bd.Lang); lvi.SubItems.Add(bd.Id); lvi.SubItems.Add(bd.Version); lvi.SubItems.Add(bd.Encoding); Valid = _fv2Validator.ValidatingFB2File(bd.Path); if (string.IsNullOrEmpty(Valid)) { Valid = "Да"; lvi.ForeColor = FilesWorker.isFB2File(bd.Path) ? Color.FromName("WindowText") : Colors.ZipFB2ForeColor; } else { Valid = "Нет"; lvi.ForeColor = Colors.FB2NotValidForeColor; } lvi.SubItems.Add(Valid); lvi.SubItems.Add(GetFileLength(bd.Path)); lvi.SubItems.Add(GetFileCreationTime(bd.Path)); lvi.SubItems.Add(FileLastWriteTime(bd.Path)); // заносим группу в хеш, если она там отсутствует AddBookGroupInHashTable(htBookGroups, lvGroup); // присваиваем группу книге listViewFB2Files.Groups.Add((ListViewGroup)htBookGroups[fb2BookList.Group]); lvi.Group = (ListViewGroup)htBookGroups[fb2BookList.Group]; listViewFB2Files.Items.Add(lvi); } }
// ============================================================================================= // ВСПОМОГАТЕЛЬНЫЕ МЕТОДЫ ДЛЯ BACKGROUNDWORKER // ============================================================================================= #region BackgroundWorker: Вспомогательные методы private void validateFile(ListViewItem lvi, ref FB2Validator fv2Validator) { string FilePath = lvi.SubItems[0].Text; if (File.Exists(FilePath)) { string Msg = fv2Validator.ValidatingFB2File(FilePath); lvi.SubItems[(int)ResultViewDupCollumnEnum.Validate].Text = Msg == string.Empty ? "Да" : "Нет"; if (!string.IsNullOrEmpty(Msg)) { lvi.ForeColor = Colors.FB2NotValidForeColor; } else { lvi.ForeColor = FilesWorker.isFB2File(FilePath) ? Color.FromName("WindowText") : Colors.ZipFB2ForeColor; } } }
/// <summary> /// генерация списка fb2-файлов из папки /// возвращает: список fb2-файлов из папки, либо null, если fb2 файлов в архиве не было /// </summary> /// <param name="sFromDir"> - папка-источник;</param> /// <param name="bSort">true - сортировать список;</param> /// <param name="bFB2Only">true - список только fb2-файлов</param> public static List <string> MakeFileListFromDir(string sFromDir, bool bSort, bool bFB2Only) { List <string> lFilesList = null; if (Directory.Exists(sFromDir)) { string [] files = Directory.GetFiles(sFromDir); if (files.Length != 0) { lFilesList = new List <string>(); int nFB2 = 0; foreach (string sFile in files) { if (bFB2Only) { if (FilesWorker.isFB2File(sFile)) { lFilesList.Add(sFile); ++nFB2; } } else { lFilesList.Add(sFile); } } if (bFB2Only && nFB2 == 0) { return(null); } if (bSort) { lFilesList.Sort(); } } } return(lFilesList); }
// поиск одинаковых fb2-файлов private void bw_DoWork(object sender, DoWorkEventArgs e) { m_dtStart = DateTime.Now; BackgroundWorker worker = sender as BackgroundWorker; ControlPanel.Enabled = false; m_FilesList.Clear(); if (string.IsNullOrEmpty(m_fromXmlPath)) { /* непрерывный поиск */ StatusLabel.Text += "Создание списка файлов для поиска копий fb2 книг...\r"; List <string> lDirList = new List <string>(); // сканировать все подпапки исходной папки m_AllDirs = FilesWorker.recursionDirsSearch(m_SourceDir, ref lDirList, true); m_AllFiles = FilesWorker.makeFilesListFromDirs(ref worker, ref e, ref lDirList, ref m_FilesList, true); // проверка, есть ли хоть один файл в папке для сканирования if (m_AllFiles == 0) { MessageBox.Show("В папке сканирования не найдено ни одного файла!\nРабота прекращена.", m_sMessTitle, MessageBoxButtons.OK, MessageBoxIcon.Information); return; } this.Text += String.Format(": Всего {0} каталогов; {1} файлов", m_AllDirs, m_AllFiles); StatusLabel.Text += String.Format("Осталось проверить {0} книг...\r", m_AllFiles); lDirList.Clear(); } else { /* возобновление поиска */ // загрузка данных из xml StatusLabel.Text += "Возобновление поиска невалидных fb2 книг из xml файла:\r"; StatusLabel.Text += m_fromXmlPath + "\r"; StatusLabel.Text += "Загрузка списка непроверенных книг из xml файла...\r"; XElement xTree = XElement.Load(m_fromXmlPath); //загрузка данных о ходе сравнения XElement xCompareData = xTree.Element("SearchData"); m_AllDirs = Convert.ToInt32(xCompareData.Element("AllDirs").Value); m_AllFiles = Convert.ToInt32(xCompareData.Element("AllFiles").Value); this.Text += String.Format(": Всего {0} каталогов; {1} файлов", m_AllDirs, m_AllFiles); // заполнение списка необработанных файлов IEnumerable <XElement> files = xTree.Element("NotWorkingFiles").Elements("File"); int NotWorkingFiles = files.ToList().Count; StatusLabel.Text += String.Format("Осталось проверить {0} книг...\r", NotWorkingFiles.ToString()); ProgressBar.Maximum = NotWorkingFiles; int i = 0; foreach (XElement element in files) { m_FilesList.Add(element.Value); worker.ReportProgress(i++); } // загрузка из xml-файла в хэш-лист данных о невалидных книгах StatusLabel.Text += "Создание визуального списка невалидных книг из xml файла...\r"; files = xTree.Element("FB2NotValidate").Elements("File"); ProgressBar.Maximum = files.ToList().Count; i = 0; foreach (XElement element in files) { if ((worker.CancellationPending)) { e.Cancel = true; return; } createNotValidateBookItem(element.Value, m_fb2Genres, m_fv2Validator, m_sharpZipLib); worker.ReportProgress(i++); } } ControlPanel.Enabled = true; if ((worker.CancellationPending)) { e.Cancel = true; return; } // Создание списка невалидных fb2-книг searchNotValidateFiles(sender, e, m_FilesList); if (m_autoResizeColumns) { MiscListView.AutoResizeColumns(m_listViewFB2Files); } }
/// <summary> /// Хеширование файлов в контексте Id книг: /// Одинаковый Id Книги (копии и/или разные версии правки одной и той же книги) /// </summary> /// <param name="FilesList">Список файлов для сканированияl</param> /// <param name="htFB2ForID">Хеш Таблица с книгами с одинаковыми ID</param> /// <returns>Признак непрерывности обработки файлов</returns> public bool FilesHashForIDParser(BackgroundWorker bw, DoWorkEventArgs e, Label StatusLabel, ProgressBar ProgressBar, string TempDir, List <string> FilesList, HashtableClass htFB2ForID) { StatusLabel.Text += "Хэширование по Id книг...\r"; ProgressBar.Maximum = FilesList.Count; ProgressBar.Value = 0; List <string> FinishedFilesList = new List <string>(); for (int i = 0; i != FilesList.Count; ++i) { if (FilesWorker.isFB2File(FilesList[i])) { // заполнение хеш таблицы данными о fb2-книгах в контексте их ID MakeFB2IDHashTable(null, FilesList[i], ref htFB2ForID); // обработанные файлы FinishedFilesList.Add(FilesList[i]); } else { if (FilesWorker.isFB2Archive(FilesList[i])) { try { if (_sharpZipLib.UnZipFB2Files(FilesList[i], TempDir) != -1) { string[] files = Directory.GetFiles(TempDir); if (files.Length > 0) { if (FilesWorker.isFB2File(files[0])) { // заполнение хеш таблицы данными о fb2-книгах в контексте их ID MakeFB2IDHashTable(FilesList[i], files[0], ref htFB2ForID); // обработанные файлы FinishedFilesList.Add(FilesList[i]); } } } } catch (Exception ex) { Debug.DebugMessage( FilesList[i], ex, "Дубликатор.CompareForm.FilesHashForIDParser(): Хеширование файлов в контексте Id книг." ); } FilesWorker.RemoveDir(TempDir); } } bw.ReportProgress(i); // отобразим данные в контролах if (bw.CancellationPending) { // удаление из списка всех файлов обработанных книг WorksWithBooks.removeFinishedFilesInFilesList(ref FilesList, ref FinishedFilesList); e.Cancel = true; return(false); } } // удаление элементов таблицы, value (списки) которых состоят из 1-го элемента (это не копии) _compComm.removeNotCopiesEntryInHashTable(htFB2ForID); // удаление из списка всех файлов обработанных книг WorksWithBooks.removeFinishedFilesInFilesList(ref FilesList, ref FinishedFilesList); return(true); }
/// <summary> /// Размер обрабатываемого файла /// </summary> /// <param name="FilePatch">Путь к файлу</param> private string getFileLength(string FilePatch) { FileInfo fi = new FileInfo(FilePatch); return(fi.Exists ? FilesWorker.FormatFileLength(fi.Length) : string.Empty); }
// Обработка файлов private void bw_DoWork(object sender, DoWorkEventArgs e) { ProgressBar.Value = 0; StatusTextBox.Text += "Создание списка файлов для Автокорректировки...\r\n"; foreach (ListViewItemInfo Item in m_ListViewItemInfoList) { if (Item.IsDirListViewItem) { m_SourceDirs.Add(Item.FilePathSource); } else { m_SourceRootFiles.Add(Item.FilePathSource); } } m_NotWorkingFilesList.Clear(); foreach (string dir in m_SourceDirs) { m_AllDirs += FilesWorker.recursionDirsSearch(dir, ref m_DirsList, true); } m_AllFiles = FilesWorker.makeFilesListFromDirs( ref m_bw, ref e, ref m_DirsList, ref m_NotWorkingFilesList, true ); m_NotWorkingFilesList.AddRange(m_SourceRootFiles); m_AllFiles += m_SourceRootFiles.Count; // только теперь добавляем корневой каталог, если в нем выделен / помечен хоть один файл if (m_SourceRootFiles.Count > 0) { m_DirsList.Add(m_SourceRootDir); ++m_AllDirs; } ControlPanel.Enabled = true; if (m_bw.CancellationPending) { e.Cancel = true; return; } // проверка, есть ли хоть один файл в папке для сканирования if (m_AllFiles == 0) { MessageBox.Show( "В папке сканирования не найдено ни одного файла!\r\nРабота прекращена.", m_sMessTitle, MessageBoxButtons.OK, MessageBoxIcon.Information ); return; } ControlPanel.Enabled = true; // Автокорреетировка книг StatusTextBox.Text += "Запуск автокорректировки fb2-файлов...\r\n"; // при пакетной обработке (не прерывать обработку на вылете корректировки, а переходим к обработке следующей книги) BooksAutoCorrectProcessingModeEnum AutoCorrectProcessingMode = (m_NotWorkingFilesList.Count == 1) ? BooksAutoCorrectProcessingModeEnum.OneBookProcessing : BooksAutoCorrectProcessingModeEnum.BatchProcessing; autoCorrect( AutoCorrectProcessingMode, ref m_bw, ref e, ref m_NotWorkingFilesList, ref m_WorkingFilesList, false ); if (m_bw.CancellationPending) { e.Cancel = true; return; } }
/// <summary> /// Добавление Группы в Список Групп /// </summary> /// <param name="bw">BackgroundWorker</param> /// <param name="e">DoWorkEventArgs</param> /// <param name="doc">xml документ - объект класса XDocument, в который заносятся данные на книги Групп</param> /// <param name="fb2BookList">Список данных fb2 книг для конкретной Группы</param> /// <param name="BookInGroups">Число книг в Группе</param> /// <param name="GroupCountInGroups">Счетчик числа Групп</param> private void addAllBookInGroup(BackgroundWorker bw, DoWorkEventArgs e, XDocument doc, FB2FilesDataInGroup fb2BookList, ref int BookInGroups, ref int GroupCountInGroups, ref StatusView sv) { BookInGroups += fb2BookList.Count; // Добавление Группы в Список Групп XElement xeGroup = null; doc.Root.Element("Groups").Add( xeGroup = new XElement( "Group", new XAttribute("number", 0), new XAttribute("count", fb2BookList.Count), new XAttribute("name", fb2BookList.Group) ) ); int BookNumber = 0; // номер Книги (Book number) В Группе (Group) int BookCountInGroup = 0; // число Книг (Group count) в Группе (Group) foreach (BookData bd in fb2BookList) { if (bw.CancellationPending) { e.Cancel = true; return; } ++sv.AllFB2InGroups; // число книг во всех группах одинаковых книг string sForeColor = "WindowText"; if (FilesWorker.isFB2Archive(bd.Path)) { sForeColor = Colors.ZipFB2ForeColor.Name; } string Validation = _fv2Validator.ValidatingFB2File(bd.Path); if (string.IsNullOrEmpty(Validation)) { Validation = "Да"; sForeColor = FilesWorker.isFB2File(bd.Path) ? "WindowText" : Colors.ZipFB2ForeColor.Name; } else { Validation = "Нет"; sForeColor = Colors.FB2NotValidForeColor.Name; } // Добавление Книги в Группу xeGroup.Add( new XElement("Book", new XAttribute("number", ++BookNumber), new XElement("Group", fb2BookList.Group), new XElement("Path", bd.Path), new XElement("BookTitle", MakeBookTitleString(bd.BookTitle)), new XElement("Authors", MakeAuthorsString(bd.Authors)), new XElement("Genres", MakeGenresString(bd.Genres)), new XElement("BookLang", bd.Lang), new XElement("BookID", bd.Id), new XElement("Version", bd.Version), new XElement("FB2Authors", MakeAuthorsString(bd.FB2Authors)), new XElement("Encoding", bd.Encoding), new XElement("Validation", Validation), new XElement("FileLength", GetFileLength(bd.Path)), new XElement("FileCreationTime", GetFileCreationTime(bd.Path)), new XElement("FileLastWriteTime", FileLastWriteTime(bd.Path)), new XElement("ForeColor", sForeColor), new XElement("BackColor", "Window"), new XElement("IsChecked", false) ) ); xeGroup.SetAttributeValue("count", ++BookCountInGroup); if (!xeGroup.HasElements) { xeGroup.Remove(); } } // по всем книгам Группы ++GroupCountInGroups; }
/// <summary> /// Длина файла /// </summary> public string GetFileLength(string sFilePath) { FileInfo fi = new FileInfo(sFilePath); return(fi.Exists ? FilesWorker.FormatFileLength(fi.Length) : string.Empty); }
/// <summary> /// Валидация fb2, fb2.zip ли fbz файлов по пути FilePath, согласно схеме SchemePath /// </summary> /// <param name="FilePath">Путь к проверяемому файлу</param> /// <param name="SchemePath">Путь к схеме fb2у</param> /// <param name="IsZip">Ссылка, проверяемый файл - архив (true)?</param> /// <returns>Пустая строка, файл валиден; Строка с сообщением, если файл невалиден</returns> private string validate(string FilePath, string SchemePath, ref bool IsZip) { string [] files = null; if (FilesWorker.isFB2Archive(FilePath)) { IsZip = true; _sharpZipLib.UnZipFB2Files(FilePath, _TempDir); files = Directory.GetFiles(_TempDir); } string FB2Path = (files != null && files.Length > 0) ? files[0] : FilePath; XmlDocument xmlDoc = new XmlDocument(); try { xmlDoc.Load(FB2Path); // Проверка наличия атрибутов корневого тега <FictionBook int FictionBookTagIndex = xmlDoc.InnerXml.IndexOf("<FictionBook", StringComparison.CurrentCulture); if (FictionBookTagIndex != -1) { Regex regex = new Regex("<FictionBook [^>]+>", RegexOptions.None); Match m = regex.Match(xmlDoc.InnerXml); if (m.Success) { string FBookTag = m.Value; int xmlnsIndex = FBookTag.IndexOf("xmlns=\"http://www.gribuser.ru/xml/fictionbook/2.", StringComparison.CurrentCulture); int xmlnsLinkIndex = FBookTag.IndexOf("=\"http://www.w3.org/1999/xlink\"", StringComparison.CurrentCulture); if (xmlnsIndex == -1) { return("Файл: " + FilePath + "\r\nВ корневом теге <FictionBook отсутствует атрибут xmlns=\"http://www.gribuser.ru/xml/fictionbook/2.0\""); } if (xmlnsLinkIndex == -1) { return("Файл: " + FilePath + "\r\nВ корневом теге <FictionBook отсутствует атрибут xmlns:l=\"http://www.w3.org/1999/xlink\""); } } } // Проверка обязательных тегов string TI = string.Empty; string DI = string.Empty; try { Regex regDesc = new Regex(@"<description>\s*?.+?\s*?</description>", RegexOptions.Multiline | RegexOptions.Singleline); Match mDesc = regDesc.Match(xmlDoc.InnerXml); if (mDesc.Success) { string Desc = mDesc.Value; Regex regTitleInfo = new Regex(@"<title-info>\s*?.+?\s*?</title-info>", RegexOptions.Multiline | RegexOptions.Singleline); Match mTI = regTitleInfo.Match(Desc); if (mTI.Success) { TI = mTI.Value; } Regex regDocumentInfo = new Regex(@"<document-info>\s*?.+?\s*?</document-info>", RegexOptions.Multiline | RegexOptions.Singleline); Match mDI = regDocumentInfo.Match(Desc); if (mDI.Success) { DI = mDI.Value; } } else { regDesc = new Regex("(?:<description[^/]+?(?:\"[^\"]*\"|'[^']*')?>)", RegexOptions.Multiline | RegexOptions.Singleline); mDesc = regDesc.Match(xmlDoc.InnerXml); return(mDesc.Success ? string.Format("Файл: {0}\r\nВ теге <description> присутствует(ет) аттрибут(ы), что недопустимо по стандарту FictionBook", FilePath) : string.Format("Файл: {0}\r\nОтсутствует раздел описания книги <description>", FilePath)); } } catch (RegexMatchTimeoutException ex) { Debug.DebugMessage( FilePath, ex, "FB2Validator.validate(): Проверка обязательных разделов fb2 структуры. Исключение RegexMatchTimeoutException." ); } catch (Exception ex) { Debug.DebugMessage( FilePath, ex, "FB2Validator.validate(): Проверка обязательных разделов fb2 структуры. Исключение Exception." ); } if (!string.IsNullOrEmpty(TI)) { // Проверка <genre> if (TI.IndexOf("<genre", StringComparison.CurrentCulture) == -1) { return(string.Format("Файл: {0}\r\nОтсутствует тег <genre> книги", FilePath)); } else { Regex regGenre = new Regex(@"(<genre ?/>)|(<genre></genre>)", RegexOptions.None); Match mGenre = regGenre.Match(TI); if (mGenre.Success) { return(string.Format("Файл: {0}\r\nТег <genre> книги 'пустой'", FilePath)); } } // Проверка <lang> if (TI.IndexOf("<lang", StringComparison.CurrentCulture) == -1) { return(string.Format("Файл: {0}\r\nОтсутствует тег <lang> книги", FilePath)); } else { Regex regLang = new Regex(@"(<lang ?/>)|(<lang></lang>)", RegexOptions.None); Match mLang = regLang.Match(TI); if (mLang.Success) { return(string.Format("Файл: {0}\r\nТег <lang> книги 'пустой'", FilePath)); } else { regLang = new Regex(@"(?<=<lang>)[^<]+(?=</lang>)", RegexOptions.None); mLang = regLang.Match(TI); if (mLang.Success) { if (mLang.Value.Length > 2) { return(string.Format("Файл: {0}\r\nТег Название языка книги (тег <lang>) не может быть более 2 символов.\r\nЗначение тега <lang>: '{1}'", FilePath, mLang.Value)); } } } } // Проверка <author> if (TI.IndexOf("<author", StringComparison.CurrentCulture) == -1) { return(string.Format("Файл: {0}\r\nОтсутствует тег <author> Автора книги", FilePath)); } else { Regex regAuthor = new Regex(@"(<author ?/>)|(<author></author>)", RegexOptions.None); Match mAuthor = regAuthor.Match(TI); if (mAuthor.Success) { return(string.Format("Файл: {0}\r\nТег <author> Автора книги 'пустой'", FilePath)); } } // Проверка <book-title> if (TI.IndexOf("<book-title", StringComparison.CurrentCulture) == -1) { return(string.Format("Файл: {0}\r\nОтсутствует тег <book-title> Названия книги", FilePath)); } else { Regex regBT = new Regex(@"(<book-title ?/>)|(<book-title></book-title>)", RegexOptions.None); Match mBT = regBT.Match(TI); if (mBT.Success) { return(string.Format("Файл: {0}\r\nТег <book-title> Названия книги 'пустой'", FilePath)); } } } else { return(string.Format("Файл: {0}\r\nОтсутствует раздел описания книги <title-info>", FilePath)); } if (!string.IsNullOrEmpty(DI)) { // Проверка id книги if (DI.IndexOf("<id", StringComparison.CurrentCulture) == -1) { return("Файл: " + FilePath + "\r\nОтсутствует идентификатор книги тег <id>"); } else { Regex regID = new Regex(@"(<id ?/>)|(<id></id>)", RegexOptions.None); Match mID = regID.Match(DI); if (mID.Success) { return(string.Format("Файл: {0}\r\nИдентификатор книги тег <id> 'пустой'", FilePath)); } } } else { return(string.Format("Файл: {0}\r\nОтсутствует раздел описания книги <document-info>", FilePath)); } } catch (Exception ex) { return(string.Format("{0}\r\n\r\nФайл: {1}", ex.Message, FilePath)); } Cursor.Current = Cursors.WaitCursor; string fb2FileNamespaceURI = xmlDoc.DocumentElement.NamespaceURI; using (Stream xmlSchemeFile = new FileStream(SchemePath, FileMode.Open)) { XmlSchemaSet sc = new XmlSchemaSet(); try { if (fb2FileNamespaceURI.Equals(_aFB21Namespace)) { sc.Add(_aFB21Namespace, XmlReader.Create(xmlSchemeFile)); } else { sc.Add(_aFB20Namespace, XmlReader.Create(xmlSchemeFile)); } } catch (System.Xml.Schema.XmlSchemaException ex) { return(string.Format( "Файл: {0}\r\n{1}\r\nСтрока: {2}; Позиция: {3}", FilePath, ex.Message, ex.LineNumber, ex.LinePosition )); } XmlReaderSettings settings = new XmlReaderSettings(); settings.ValidationType = ValidationType.Schema; settings.Schemas = sc; XmlReader reader = XmlReader.Create(FB2Path, settings); try { while (reader.Read()) { ; } reader.Close(); Cursor.Current = Cursors.Default; return(string.Empty); } catch (System.Xml.Schema.XmlSchemaException ex) { reader.Close(); Cursor.Current = Cursors.Default; return(string.Format( "Файл: {0}\r\n{1}\r\nСтрока: {2}; Позиция: {3}", FilePath, ex.Message, ex.LineNumber, ex.LinePosition )); } catch (Exception ex) { reader.Close(); Cursor.Current = Cursors.Default; return(string.Format("Файл: {0}\r\n{1}", FilePath, ex.Message)); } } }