Пошаговые инструкции Для начинающих 13 мин

Как преобразовать JSON в XML в n8n и скачать файл

Соберите один XML из заказов: 10 шагов, готовый workflow и учебный файл. Проверьте кириллицу, спецсимволы, нули и данные после обратного чтения.

n8n JSON XML

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

Результат инструкции

Получим orders-demo.xml с корнем orders и тремя элементами order. В каждом будут id, name и quantity. Номера 001, 002 и 003 останутся строками, количество 0 не исчезнет, амперсанд в названии товара не сломает документ.

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

Что понадобится

  • Отдельный новый workflow в n8n. Проверено на n8n 2.42.4, XML 1, Convert to File 1.1 и Code 2.
  • Учебные заказы из статьи. Внешние аккаунты, ключи и реальные клиентские данные не нужны.
  • Текстовый редактор или браузер для просмотра XML. Файл содержит UTF-8, а не Windows-1251.

Как установить n8n локально через Docker

Шаг 1. Импортируйте готовую схему

Скачать n8n-json-to-xml-export.json

Создайте новый workflow и выберите Import from File. Загрузите JSON и сохраните его под отдельным названием. Публиковать workflow не нужно: он запускается кнопкой вручную. Восемь узлов идут последовательно: Manual Trigger → Sample Orders → Prepare XML → Build XML → Read XML → Verify XML → Make File → Check File.

Sample Orders, Prepare XML, Verify XML и Check File — Code, язык JavaScript, режим Run Once for All Items. Два XML-узла создают документ и читают его обратно. Make File превращает проверенный текст в binary. Названия узлов оставьте как в схеме: код использует ссылки на них.

Шаг 2. Проверьте исходные заказы

Откройте Sample Orders. При ручной сборке вставьте:

javascript
return [
  {
    "order_id": "001",
    "product": "Чай & кофе",
    "quantity": 2
  },
  {
    "order_id": "002",
    "product": "Блокнот",
    "quantity": 0
  },
  {
    "order_id": "003",
    "product": "Лампа \"Старт\"",
    "quantity": 1
  }
].map(json => ({ json }));

На выходе должны быть три отдельных items, не один объект с массивом внутри. Номер передаётся строкой в кавычках. Если сделать из 001 число, нули пропадут до преобразования в XML, и узел не сможет их восстановить.

У второго товара quantity равно 0. Это корректное значение нашего примера. Пустая строка, null и неизвестное количество не равны нулю: схема отклонит их, а не заменит автоматически.

Шаг 3. Соберите один объект для экспорта

В Prepare XML вставьте следующий код:

javascript
const items = $input.all();
if (items.length < 1 || items.length > 20) throw new Error('rows_limit');
const ids = new Set();
const orders = items.map(({ json: row }) => {
  if (Object.keys(row).sort().join('|') !== 'order_id|product|quantity') throw new Error('fields_invalid');
  if (typeof row.order_id !== 'string' || !/^\d{3}$/.test(row.order_id) || ids.has(row.order_id)) {
    throw new Error('id_invalid_or_duplicate');
  }
  ids.add(row.order_id);
  if (typeof row.product !== 'string' || !row.product.trim() || row.product.length > 120 ||
      !row.product.isWellFormed() || /[\u0000-\u001f\u007f\ufffe\uffff]/.test(row.product)) {
    throw new Error('product_invalid');
  }
  if (!Number.isSafeInteger(row.quantity) || row.quantity < 0) throw new Error('quantity_invalid');
  return { id: row.order_id, name: row.product, quantity: String(row.quantity) };
});
return [{ json: { order: orders }, pairedItem: items.map((_, item) => ({ item })) }];

Проверка принимает от одной до двадцати записей. У каждой должны быть ровно order_id, product и quantity; номера уникальные и трёхзначные, количество — неотрицательное безопасное целое число. Название товара ограничено 120 символами, недопустимые управляющие символы и повреждённые Unicode-строки отклоняются. Это учебный контракт данных, не универсальные ограничения XML.

После проверки получается один item с полем order, внутри которого массив заказов. Поля переименованы в id, name и quantity, а числа явно переведены в текст. У XML нет автоматической памяти о JSON-типах: после обратного чтения количество будет строкой. Сравнивать его нужно с тем же строковым представлением, не менять номера на числа.

Значения не нужно заранее заменять на &amp; или &lt;. Это сделает XML-сериализатор. Предварительное экранирование изменит буквальный текст: вместо амперсанда получатель может увидеть запись &amp;. Названия тегов заданы в коде, а не берутся из пользовательских ключей.

Шаг 4. Настройте JSON to XML

В Build XML выберите Mode: JSON to XML. Укажите:

Настройка Значение Для чего
Property Name xml Имя выходного JSON-поля с XML-строкой
Root Name orders Один общий корень документа
Headless Выключено Сохранить XML-декларацию
Cdata Выключено Обычное экранирование значений сериализатором

Attribute Key оставьте $, Character Key — _, Allow Surrogate Chars — выключено. В нашем объекте нет атрибутов или смешанного содержимого, поэтому эти специальные ключи не используются.

В проверенном n8n поле Property Name в режиме JSON to XML задаёт, куда записать результат. Узел сериализует весь входной item.json, а не только поле с таким именем. Поэтому вход здесь — объект с order, а выход — объект с xml. Не оборачивайте вход дополнительно в xml: это изменит структуру документа.

На выходе Build XML один item, внутри xml — такой документ:

xml
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<orders>
  <order>
    <id>001</id>
    <name>Чай &amp; кофе</name>
    <quantity>2</quantity>
  </order>
  <order>
    <id>002</id>
    <name>Блокнот</name>
    <quantity>0</quantity>
  </order>
  <order>
    <id>003</id>
    <name>Лампа "Старт"</name>
    <quantity>1</quantity>
  </order>
</orders>

Чай & кофе записан в файле как Чай &amp; кофе. Это правильное представление амперсанда в XML, не ошибка кодировки. Кавычки внутри текста элемента допускаются как есть. Символы < и > в значениях сериализатор тоже обрабатывает; не подставляйте их в строку с тегами вручную.

Шаг 5. Настройте обратное чтение

В Read XML выберите Mode: XML to JSON и следующие параметры:

Настройка Значение Для чего
Property Name xml Прочитать строку из Build XML
Explicit Array Включено Одинаковая структура даже для одного заказа
Explicit Root Включено Сохранить уровень orders
Merge Attributes Выключено Не смешивать атрибуты с элементами

Ignore Attributes, Normalize, Normalize Tags и Trim оставьте выключенными. Здесь читается только что созданный учебный документ, а не произвольный файл извне. При Explicit Array текстовые элементы тоже становятся массивами: id выглядит как ["001"], quantity — как ["2"]. Это ожидаемый результат, не лишние дубли.

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

Шаг 6. Сверьте данные с источником

В Verify XML вставьте:

javascript
const parsed = $input.first().json;
const source = $('Sample Orders').all().map(item => item.json);
const orders = parsed.orders?.order;
if (Object.keys(parsed).join('|') !== 'orders' || !Array.isArray(orders) || orders.length !== source.length) {
  throw new Error('orders_structure_mismatch');
}
for (let i = 0; i < source.length; i++) {
  const actual = orders[i];
  const expected = { id: [source[i].order_id], name: [source[i].product], quantity: [String(source[i].quantity)] };
  if (JSON.stringify(actual) !== JSON.stringify(expected)) throw new Error('order_content_mismatch');
}
const xml = $('Build XML').first().json.xml;
if (typeof xml !== 'string' || !xml.startsWith('<?xml version="1.0" encoding="UTF-8"')) {
  throw new Error('xml_declaration_required');
}
return [{ json: { xml, count: source.length, verified: true } }];

Код проверяет корень orders, число заказов и все три значения каждого заказа в исходном порядке. Источник сравнения — Sample Orders, а не промежуточный уже преобразованный объект. Поэтому пропуск поля или изменение значения должны остановить схему.

Успешное обратное чтение не заменяет проверку XSD. Наш файл может быть корректным XML и при этом не подходить конкретному API. Здесь verified означает только совпадение с учебным контрактом и источником.

Шаг 7. Создайте скачиваемый файл

В Make File выберите Convert to File → Convert to Text File. Заполните поля:

  • Text Input Field: xml.
  • Put Output File in Field: export.
  • В Options укажите File Name: orders-demo.xml и Encoding: utf8.
  • Add Byte Order Mark (BOM): выключено.

Имя export — это ключ в binary, а не путь на диске сервера. Имя orders-demo.xml — имя скачиваемого файла. Расширение не перекодирует текст: Encoding должно соответствовать UTF-8 в XML-декларации.

У Convert to Text File в проверенной версии нет поля MIME Type: он помечает binary как text/plain, даже если файл назван .xml. Байты при этом остаются корректным XML. Мы проверили это отдельно. Если позже API потребует application/xml, Content-Type нужно явно согласовать в узле отправки; простое переименование файла его не меняет.

Шаг 8. Проверьте байты файла

В Check File вставьте:

javascript
const items = $input.all();
if (items.length !== 1 || Object.keys(items[0].binary ?? {}).join('|') !== 'export') {
  throw new Error('one_export_file_required');
}
const item = items[0];
if (item.binary.export.fileName !== 'orders-demo.xml') throw new Error('file_name_invalid');
const bytes = await this.helpers.getBinaryDataBuffer(0, 'export');
const expected = Buffer.from($('Verify XML').first().json.xml, 'utf8');
if (!bytes.equals(expected)) throw new Error('file_bytes_mismatch');
return [{ json: {
  file_name: 'orders-demo.xml', count: $('Verify XML').first().json.count,
  bytes: bytes.length, verified: true, action_performed: false
}, binary: item.binary }];

getBinaryDataBuffer читает настоящий файл, в том числе при хранении binary на диске. Служебное поле binary.export.data не следует считать содержимым XML. Код требует один файл с ожидаемым именем и побайтовое совпадение с проверенной XML-строкой в UTF-8.

Make File не сохраняет прежние JSON-поля на выходе. Поэтому Check File берёт проверенный XML и число записей по ссылке на Verify XML, а сам binary передаёт дальше без изменения. Здесь не создаётся новый файл ручной склейкой или Base64-кодированием.

Шаг 9. Запустите workflow и проверьте ответ

Выполните всю цепочку от Manual Trigger. Все восемь узлов должны завершиться успешно. В JSON последнего узла ожидаются:

json
{
  "file_name": "orders-demo.xml",
  "count": 3,
  "bytes": 381,
  "verified": true,
  "action_performed": false
}

В учебном образце файл занимает 381 байт. Это размер конкретных данных и форматирования, не требование для ваших будущих выгрузок. Главное — verified: true, count: 3 и наличие binary.export. action_performed: false означает, что внешней отправки не было.

В Check File откройте Binary, выберите export и скачайте файл. В текстовом редакторе проверьте декларацию UTF-8, один корень orders, три order, номера 001–003 и нулевое количество у блокнота. Для сравнения доступен точный образец, полученный запуском этой схемы:

Открыть учебный XML-файл

Шаг 10. Проверьте спецсимволы и неверный вход

В Sample Orders временно замените product первого заказа на <b>Чай</b>. Запустите всю схему. В XML появится &lt;b&gt;Чай&lt;/b&gt;, а Read XML вернёт буквальную строку <b>Чай</b>. Это не вложенный тег b, а текст товара. Проверка должна пройти.

Затем задайте quantity: -1. Prepare XML должен завершиться ошибкой quantity_invalid; файл не создаётся. Верните исходный пример и повторите запуск. Дополнительно можно оставить один заказ: при Explicit Array схема по-прежнему должна пройти.

Если Sample Orders вернёт ноль items, последующие узлы не запустятся и файла не будет. Не считайте такой запуск успешной пустой выгрузкой. Для пустого документа нужен отдельный заранее определённый сценарий, которого здесь нет.

Если результат отличается

Симптом Что проверить Как исправить
Получилось несколько XML-документов На входе Build XML несколько items Собрать один item в Prepare XML
Лишний уровень вложенности Вход обёрнут в поле xml Передавать объект с массивом order
orders_structure_mismatch Root Name и Explicit Root Вернуть orders и сохранение корня
order_content_mismatch Explicit Array, значения и порядок Сверить Read XML с Sample Orders
file_bytes_mismatch Encoding и Add BOM Вернуть utf8 без BOM

Как подготовить обмен с реальной системой

Сначала получите описание формата от получателя: точный корень, имена и порядок полей, обязательные атрибуты, пространства имён и правила для пустых значений. Учебные orders и order не являются стандартом 1С, CommerceML или любого маркетплейса. Менять их нужно вместе с проверкой структуры, а не только с названием файла.

Для отправки используйте отдельный тестовый контур и согласованный Content-Type. До подтверждения успешного приёма не отмечайте заказ выгруженным. Этот workflow ничего не отправляет и не проверяет чужие credentials. Источник с рабочими или персональными данными подключайте только с разрешённым доступом и настройками хранения executions.

Обратная задача: XML в JSON в n8n

Как отправить файл через HTTP Request

Что проверено редакцией

18 октября 2026 года точная публичная схема проверена на n8n 2.42.4 в отдельном Docker-экземпляре с binary на диске. Все 38 сценариев прошли: три, один и двадцать заказов, обратный порядок, нули, Unicode, пробелы, кавычки, амперсанд, буквальные теги и HTML-сущности; Cdata как отдельная диагностика; неверные типы, номера, дубли, пустой и слишком длинный текст, управляющие символы, непарный суррогат, отрицательные, дробные и небезопасные числа, пропущенные и лишние поля; неверный корень, Explicit Root, Explicit Array, Property Name, Headless, источник файла, имя, binary-поле, BOM и UTF-16. Пустой источник не создал файл. XML строился и читался штатным узлом XML, файл создавался Convert to File. Образец UTF-8 на 381 байт дополнительно разобран независимым Python ElementTree: все три заказа совпали. Подтверждён MIME text/plain у Convert to Text File, это отмечено в статье. Контейнер остановлен, существующие workflows не менялись. Клики редактора, ручное скачивание из n8n, Cloud, XSD, 1С и внешние API не тестировались. Обложка — AI-иллюстрация.

Частые вопросы

Property Name выбирает поле JSON для преобразования?

В режиме JSON to XML в проверенной версии это имя выходного поля с XML-строкой. Сериализуется весь входной item.json. В режиме XML to JSON это, напротив, имя входного поля с XML.

Почему количество после чтения XML стало строкой?

В XML текстовый элемент сам не хранит JSON-тип Number. В нашей схеме число заранее превращается в строку, после чтения сравнивается с ней же. Номер заказа числом делать не нужно.

Нужно вручную заменять амперсанды и угловые скобки?

Нет. При Cdata: выключено XML-сериализатор экранирует значения. Входите обычным текстом, иначе можно получить двойное экранирование.

Почему файл .xml отмечен как text/plain?

Convert to Text File в проверенной версии использует этот MIME. Расширение и байты XML от этого не меняются. Для отправки в API согласуйте Content-Type отдельно.

Можно загрузить этот файл в 1С без изменений?

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

Дальше по теме

Похожие материалы