Как текстовый файл преобразовать в xml

Обновлено: 27.06.2024

Недавно мне пришлось столкнуться с необходимостью достать текст из офисных документов (docx, xlsx, rtf, doc, xls, odt и ods). Задача осложнялась требованием представить текст в формате xml без мусора с максимально удобной для дальнейшего парсинга структурой.

Решение использовать Interop сразу отпало по причине его громоздкости, во многом избыточности, а также необходимости устанавливать на сервер MS Office. В результате, решение было найдено и воплощено на внутреннем проекте. Однако, поиск оказался настолько сложен и не тривиален в силу отсутствия каких-либо общедоступных мануалов, что мной было принято решение написать в свободное от работы время библиотеку, которая решала бы указанную задачу, а также создать написать что-то вроде инструкции, чтобы разработчики прочитав ее смогли, хотя бы поверхностно, разобраться в вопросе.

Прежде, чем перейти к описанию найденного решения, предлагаю ознакомиться с некоторыми выводами, которые были сделаны в результате моих изысканий:

Сразу оговорюсь, что в настоящий момент библиотека еще не готова, но она активно пишется (на столько, на сколько это позволяет свободное время). Предполагается, что будут написаны отдельные посты для каждого формата и параллельно, вместе с их публикацией, будет обновляться репозиторий на гитхабе, откуда можно будет получить исходники.

Работа с xlsx и docx

.xlsx

Наверняка, раз вы читаете эту статью, то уже в курсе, что docx и xlsx фактически являются zip-архивами, в которых лежит множество разных xml. Если нет, то убедиться в этом не составит труда: меняем расширение файла на zip и открываем любым архиватором. Так, наши листы документа будут лежать по следующему пути: \xl\worksheets .

У меня уже есть подготовленный excel документ, и, если открыть какой-нибудь лист по указанному ранее пути, то мы увидим примерно следующее содержимое:


Обратите внимание на то, что в ячейках, которые содержат формулы, записаны формулы (внутри тега <f> ) и результат (внутри тега <v> ). Также, ячейки с повторяющимся содержимым отмечены как shared и содержат ссылку на строку в файле sharedStrings.xml, расположенного по пути \xl .
Пока просто имейте ввиду эти особенности: как обрабатывать их будет показано ниже.

Прежде, чем писать наши классы-конвертеры, создадим интерфейс IConvertable:

Теперь все наши классы, должны будут реализовывать два метода: string Convert(Stream stream) для работы с потоком (может быть очень полезным, если необходимо получить какую-то информацию из файла без его сохранения на хосте), а также string ConvertByFile(String path) для конвертации непосредственно файла.

Создаем класс XlsxToXml , реализующий интерфейс IConvertable и подключаем через Nuget DocumentFormat.OpenXml (на момент написания, актуальной являлась версия 2.10.0).

Логику обработки документа поместим в отдельный приватный метод string SpreadsheetProcess(Stream memStream) , который будет вызываться в string Convert(Stream stream) .

Как видно, сама логика реализована в методе *string SpreadsheetProcess(Stream memStream)* :

Итак, в методе string SpreadsheetProcess(Stream memStream) происходит следующее:

В блоке using открываем документ excel из потока. За работу с xlsx в библиотеке DocumentFormat.OpenXml отвечает класс SpreadsheetDocument.

Устанавливаем каретку в начало потока и создаем объект StringBuilder sb (сразу на 1000 символов. Используем StringBuilder вместо строк, чтобы несколько оптимизировать процесс и избежать порождения лишних сущностей в виде не нужных стрингов. Также, заранее задаем начальный размер стрингбилдера, чтобы немного сэкономить времени на инициализации и выделении памяти.

Выше я писал про shared ячейки (в которых хранятся повторяемые значения). Так вот, из объекта класса SpreadsheetDocument их можно получить так:
SharedStringTable sharedStringTable = doc.WorkbookPart.SharedStringTablePart.SharedStringTable .

Далее создаем переменную, в которой будет храниться номер листа и запускаем цикл

в котором выполняется обработка каждого листа с помощью вызываемого метода
WorkSheetProcess(sb, sharedStringTable, worksheetPart, doc, sheetIndex); :


Пожалуй, в данной функции больше всего вопросов вызывает строчка:
string sheetName = doc.WorkbookPart.Workbook.Descendants<Sheet>().ElementAt(sheetIndex).Name.ToString();
То, что таким образом мы получаем имя листа, думаю понятно. Но вот, чтобы добраться до нее придется воспользоваться отладчиком и методом научного тыка. Поэтому не стесняемся, ставим точку остановки, жмакаем shift+F9(или как там у вас), открываем переменную doc (в которой лежит наш документ)->WorkbookPart->Workbook и вызываем метод Descendants(), который вернет коллекцию всех дочерних элементов типа Sheet . Ну а дальше остается по индексу получить конкретный лист, вытащить его имя и преобразовать в строку (что и сделано в коде). Как это примерно выглядит показано на рисунке ниже:

Далее по коду в цикле foreach получаем данные из листа, которые представляют собой коллекцию строк. Если внутри объекта sheetData есть какие-то элементы, то это строки, каждую из которых мы обработаем методом RowProcess :

В методе void RowProcess(Row row, StringBuilder sb, SharedStringTable sharedStringTable) происходит следующее:

В цикле foreach (Cell cell in row.Elements<Cell>()) проверяем каждую ячейку на предмет наличия в ней записанной формулы:

Если формула обнаружена, то получаем значение, вычисленное по формуле ( cellValue = cell.CellValue.InnerText; ) и переходим к следующей ячейке.
Если ячейка не содержит формулы, то мы проверяем, является ли она shared: если является, то берем значение по индексу из ранее полученной коллекции с повторяющимися значениями:

В противном случае, мы просто получаем значение из ячейки.

.docx

Начнем с того, что парсинг документов word представляет из себя куда более не тривиальную задачу по сравнению с парсингом excel-файлов.
Так, разработчику предстоит решить проблему не только парсинга содержимого, но и сохранения структуры, что подразумевает, как минимум, сохранение абзацев, обработку списков и таблиц. Так как мои рабочие задачи не подразумевали обработку графики, сносок, оглавления и т.д., в данной статье они разобраны не будут, но, я не исключаю, что когда-нибудь мне придется столкнуться с такой задачей и, я обязательно обновлю и статью, и репозиторий.

Итак, для начала пара слов о внутреннем устройстве документа. Предлагаю снова проделать процедуру с переименованием расширения файла в zip и открыть его любым архиватором. Внутри мы увидим несколько папок. Открываем папку word и находим файл document. Да, внутри лежит еще куча файлов, но они, по большому счету, для решения нашей задачи не нужны. Однако, никто вам не запрещает в них поковыряться: вдруг вам потребуется вытащить какие-нибудь стили из документа.

Как мы видим, содержимое каждого абзаца находится внутри тега w:t, который лежит внутри w:r, который также находится внутри w:p. По большому счету, эта структура является ключевой для всех документов docx, независимо от их содержимого. Обратите внимание на списки: каждый элемент также находится внутри описанной структуры, но с добавлением тегов w:numPr, внутри которого определяется уровень вложенности списка (w:ilvl) и id списка, которому принадлежит данный элемент (w:numId).

Также, хочу обратить внимание, что индексы элементов списка не хранятся в виде значения в данном файле, а, как мне кажется (во всяком случае, других версий я не нашел), формируются динамически, в зависимости от id списка, которому принадлежит элемент, уровня вложенности и порядкового номера элемента.
Аналогичная история со вложенными списками, которые отличаются от простых списков лишь тем, что у них не нулевой уровень вложенности:

Более того, данная структура сохраняется и для таблиц. Правда теперь она упакована в теги w:tr (строка) и w:tc(ячейка).


Прежде, чем начать кодить, хочу обратить внимание на один очень важный ньюанс (да-да, как в анекдоте про Петьку и Василия Ивановича). При разборе списков, особенно это касается вложенных, может возникнуть ситуация, когда пункты списка разделены какой-то вставкой текста, изображения или вообще чего угодно. Тогда возникает вопрос, когда же нам ставить закрывающий тег списка? Мое предложение попахивая костылезацией и велосипедостроением сводится к добавлению словаря, ключами которого будут выступать id списков, а значение будет соответствовать id параграфа (да, оказывается каждый параграф в документе имеет свой уникальный id), который одновременно является последним в каком-то списке. Пожалуй, написано довольно сложно, но, думаю, когда посмотрите на реализацию, станет несколько понятнее:

Dictionary<int, string> listEl = new Dictionary<int, string>(); — словарь в котором будет храниться информация о последних элементах каждого из списков.

using (WordprocessingDocument doc = WordprocessingDocument.Open(memStream, false)) — создаем объект doc класса WordprocessingDocument, в котором находится содержимое нашего документа word, но уже в структурированном (на столько, на сколько это позволяет библиотека OpenXML) виде.

StringBuilder sb = new StringBuilder(1000); — наша будущая строка с легко читаемым содержимым в формате xml.

Body docBody = doc.MainDocumentPart.Document.Body; — получаем содержимое нашего документа, с которым мы дальше и будем работать

Вызываем функцию CreateDictList(listEl, docBody); , которая пробегается в цикле foreach по всем элементам документа, и ищет последний абзац для каждого списка:

После того, как наш словарь создан, в цикле foreach перебираем все элементы в документе. На каждой итерации цикла выясняем к какому типу относится наш элемента: абзац или таблица. Если абзац, то мы должны произвести проверку, а не является ли наш абзац частью списка. И если он является элементом списка, то нужно выяснить в какой части списка находится данный абзац (начало, конец или середина) для того, чтобы корректно расставить открывающиеся и закрывающиеся теги для нашего списка. Помимо этого, также важно идентифицировать к какому именно списку относится наш элемент. В коде эта задача решается так:

Блок try-catch используется в связи с тем, что существует вероятность наличия в документе какого-то элемента, который не предусмотрен в блоке switch-case (в нашем случае, мы производим обработку только абзацев, списков и таблиц). Таким образом, если в документе есть что-то неопознанное и нами не предвиденное, то программа просто проигнорирует такой кейс.

Если элемент является частью списка, то он обрабатывается с помощью метода ListParagraph(sb, (Paragraph)element); :

По большому счету данный метод всего лишь упаковывает содержимое параграфа в теги <ul> , дополняя его информацией об id списка и уровне вложенности.

Если же, текущий элемент не является списком или таблицей, то он обрабатывается с помощью метода SimpleParagraph(sb, (Paragraph)element); :

То есть, содержимое текста просто оборачивается в тег <p>

Таблица обрабатывается в методе Table(sb, (Table)element); :

Обработка такого элемента вполне тривиальна: считываем строки, разбиваем на ячейки, из ячеек берем значения, оборачиваем в теги <cell> , которые запаковываем в в теги <row> и все это помещаем внутрь <table> .

На этом, поставленную задачу предлагаю считать решенной для документов формата docx и xlsx.

Вопросы и ответы в сфере it технологий и настройке ПК

XML конвертер


Файл с расширением XML – это текстовый файл, который используется во многих сферах деятельности: создании баз данных, веб-разработке, Java и другое. Файл может быть открыт практически в любом текстовом редакторе, а также в популярных браузерах, таких как Google Chrome, Opera, Mozilla Firefox и др. В статье вы узнаете о популярных XML-конвертерах, которые позволят как преобразовать файл в XML, так и наоборот.

XML-конвертеры

1. Office-Converter

Популярный онлайн-сервис для конвертации, который позволяет преобразовать многие файлы в формат XML. Сервисом поддерживаются такие форматы, как PDF, PHP, HTML, Excel, Docx и др.

Чтобы приступить к работе с сервисом, достаточно перейти на страницу XML-конвертера, нажать кнопку «Добавить файлы», указав путь к исходному файлу (или файлам), а затем нажать кнопку «Начните Convert». Когда сервис завершит работу, вам будет предложено сохранить преобразованные файлы на компьютер.

XML конвертер

2. CoolUtils

Следующий онлайн-сервис, позволяющий конвертировать XML-файл в один из предложенных форматов. Чтобы воспользоваться сервисом, достаточно нажать кнопку «Browse» и указать путь к исходному XML-файлу, а затем указать конечный формат, в который файл будет конвертирован.

XML конвертер

3. Zamzar

Третий онлайн-сервис, позволяющий преобразовать как в формат XML, так и наоборот. Для работы с сервисом в первом шаге укажите имеющийся на компьютере файл, вторым шагом выберите один из предложенных форматов конвертации, в третьем шаге введите свой адрес электронной почты, а затем нажмите кнопку «Convert».

XML конвертер

Спустя несколько мгновений на ваш адрес электронной почты поступит входящее письмо, в котором будет содержаться прикрепленный преобразованный файл. Вам остается лишь скачать его на компьютер.

Как сделать файл с расширением XML

Обычно файлы такого типа используются для информации, которая впоследствии будет использоваться как компонент какой-либо утилиты, приложения или интернет-ресурса. Сделать подобный файл не так уж и сложно. Работать с подобным расширением можно и без использования дополнительных программ, а только стандартными ресурсами своего домашнего компьютера.

Что это за тип файла

Многие пользователи знают о существовании различных языков для написания сайтов. Это один из них. В отличие от общеизвестного HTML он может не только создавать определенный текст, а и делать различные структуры информации.

Работать с подобными файлами можно с помощью специальных приложений, которые можно скачать с интернета, или воспользовавшись тексторвыми редактарами установленными на ПК. Отлиличия будут заключаться только в количестве возможностей и удобстве интерфейса.

Способ 1: Использование программы Visual Studio

Эта утилита всего лишь улучшенный вариант текстового редактора, имеющегося на ПК. Работа с текстом теперь будет сопровождаться выделением определенных фрагментов и автоматической корректировкой. Помимо этого, в ней имеются макеты, которые делают процесс написания кода значительно проще.

  1. Запустите программу и перейдите во вкладку «Файл».
  2. В открывшемся меню выберите пункт «Создать» и перейдите на строку «Файл».
  3. Теперь необходимо определиться с форматом. Нажмите «XML-файл».
  4. Откроется окно для работы, в котором начало будет уже написано. Автоматически используется кодировка UTF-8, но его всегда с легкостью можно изменить.
  5. Пропишите нужный код.
  6. После завершения написания, перейдите во вкладку «Файл» и выберите «Сохранить все».

Способ 2: Воспользоваться Microsoft Excel

Пользоваться этой программой умеет множество пользователей. В ней есть возможность создать файл необходимого формата даже не вдаваясь в подробности написания кода. К сожалению, возможности этой утилиты сильно ограничены и доступен совсем небольшой функционал.

Использование подобной программы может послужить хорошим выходом из ситуации, людям слабо знакомым с кодом. Помните, что переделать получившуюся таблицу в файл XML могут только последние версии этой утилиты. Давайте рассмотрим процедуру детальнее:

Способ 3: Текстовый редактор Блокнот

Использование этого способа подходит только для пользователей, которые хорошо разбираются в коде. Вызвано это тем, что подобное приложение не имеет никаких шаблонов и все команды придется прописывать собственноручно. Если вы новичок, установите какой-либо расширенный вариант редактора. Специализированные программы имеют более удобный функционал и имеют готовые шаблоны кода.

Единственное преимущество этого способа заключается в том, что нет необходимости устанавливать какое-либо дополнительное ПО. Рассмотрим, как создать файл с нужным расширением:

Кодировку можно использовать и другую.

Сохранение xml-документа

Здесь можно создать самые примитивные таблицы, но дефицит функционала делает процесс написания очень длительным и сложным.

Как вы смогли убедиться создать не сложную таблицу можно и в стандартных текстовых редакторах, но для нормальной работы с расширенными таблицами лучше установить специальные утилиты или заняться изучением языка. На чем остановить свой выбор решать только вам.

Создаём XML-файл

XML-формат предназначен для хранения данных, которые могут пригодиться в работе некоторых программ, сайтов и поддержки определённых языков разметки. Создать и открыть файл с таким форматом не сложно. Это вполне можно сделать, даже если на компьютере не установлено какое-либо специализированное программное обеспечение.

Немного об XML

Создавать XML-файлы можно как при помощи специализированных программ, так и встроенным в Windows текстовым редактором. От вида используемого ПО зависит удобство написания кода и уровень его функциональности.

Способ 1: Visual Studio

Создание документа в MS Visual Studio

Создание XML-файла в MS Visual Studio

В только что созданном файле уже будет первая строка с кодировкой и версией. По умолчанию прописана первая версия и кодировка UTF-8, которые вы можете поменять в любое время. Дальше для создания полноценного XML-файла вам нужно прописать всё то, что было в предыдущей инструкции.

Способ 2: Microsoft Excel

Можно создать XML-файл и не прописывая код, например, при помощи современных версий Microsoft Excel, который позволяет сохранять таблицы с данным расширением. Однако нужно понимать, что в этом случае создать что-то более функциональное обычной таблицы не получится.

Такой способ больше подойдёт тем, кто не хочет или не умеет работать с кодом. Однако в этом случае пользователь может столкнуться с определёнными проблемами при перезаписи файла в XML-формат. К сожалению, проделать операцию преобразования обычной таблицы в XML можно только на самых новых версиях MS Excel. Чтобы это сделать, используйте следующую пошаговую инструкцию:

Заполняем таблицу Excel

Сохранение таблицы

Выбор места сохранения

Способ 3: Блокнот

    Создайте обычный текстовый документ с расширением TXT. Разместить его можно где угодно. Откройте его.

Создание XML-файла

<?xml version="1.0" encoding="utf-8"?>

Задаём кодировку

Примерно так у вас должен выглядеть готовый результат:

Готовый документ

XML-компиляторы должны обработать этот код в виде таблицы с одной колонкой, где указаны данные о неком Иване Иванове.

Как видите в создании XML-файла нет ничего сложного. При желании его может создать любой пользователь, который более-менее умеет работать на компьютере. Однако для создания полноценного XML-файла рекомендуется изучить данный язык разметки, хотя бы на примитивном уровне.

Закрыть

Мы рады, что смогли помочь Вам в решении проблемы.

Отблагодарите автора, поделитесь статьей в социальных сетях.

Закрыть

Опишите, что у вас не получилось. Наши специалисты постараются ответить максимально быстро.

Читайте также: