Анализ XML-документов ФНС
Парсинг и анализ XML-документов ФНС: справки 2-НДФЛ и 3-НДФЛ, выписки из ЕГРЮЛ и ЕГРИП, требования и уведомления. Извлечение реквизитов, сумм и контрольных соотношений из выгрузок налоговой.
Анализ XML-документов ФНС
Область: Парсинг и интерпретация XML-файлов Федеральной налоговой службы РФ. Дополняет skill
tax_law_ru(нормативная база) иaccounting_docs_ru(первичные документы).
Структура 2-НДФЛ (Справка о доходах)
Корневой элемент: <Файл> → <Документ> → <СвНА>, <ПолучДох>, <СведДох>, <СвВыч>, <СумИтог>
| Элемент | Описание |
|---|---|
<СвНА> | Сведения о налоговом агенте (работодатель): ИНН, КПП, наименование |
<ПолучДох> | Получатель дохода (физлицо): ФИО, ИНН, дата рождения, паспорт |
<СведДох> | Доходы по месяцам: <ДохВыч> с атрибутами Месяц, КодДоход, СумДоход |
<СвВыч> | Налоговые вычеты: <ВычетСВ> с атрибутами КодВычет, СумВычет |
<СумИтог> | Итоговые суммы: доход, облагаемая база, исчислено, удержано, перечислено |
Атрибуты <Документ>
ОтчетГод— налоговый период (год)Призн— признак (1 = обычная, 2 = невозможность удержания)НомКорр— номер корректировки (00 = первичная)
Структура 3-НДФЛ (Декларация)
Корневой элемент: <Файл> → <Документ> → разделы и приложения
| Раздел | Описание |
|---|---|
| Раздел 1 | Сведения о суммах налога, подлежащих уплате/возврату |
| Раздел 2 | Расчёт налоговой базы и суммы налога |
Приложение 1 (<ДохРФ>) | Доходы от источников в РФ |
| Приложение 2 | Доходы от источников за пределами РФ |
| Приложение 3 | Доходы от предпринимательской деятельности |
| Приложение 4 | Необлагаемые доходы |
Приложение 5 (<ВычСтанд>, <ВычСоц>) | Стандартные и социальные вычеты |
Приложение 6 (<ВычИмущ>) | Имущественные вычеты при продаже |
| Приложение 7 | Имущественные вычеты при покупке |
| Приложение 8 | Расходы и вычеты по операциям с ЦБ |
Коды доходов
| Код | Значение |
|---|---|
| 1010 | Дивиденды |
| 2000 | Заработная плата |
| 2002 | Премия за производственные результаты |
| 2003 | Премия из прибыли (непроизводственная) |
| 2012 | Отпускные |
| 2300 | Пособие по временной нетрудоспособности (больничные) |
| 2510 | Оплата за налогоплательщика (аренда, питание) |
| 2610 | Материальная выгода от экономии на процентах |
| 2760 | Материальная помощь |
| 2762 | Материальная помощь при рождении ребёнка |
| 3020 | Проценты по вкладам |
| 4800 | Иные доходы |
Коды вычетов
| Код | Значение |
|---|---|
| 126 | На первого ребёнка (1 400 руб./мес.) |
| 127 | На второго ребёнка (1 400 руб./мес.) |
| 128 | На третьего и последующих (3 000 руб./мес.) |
| 129 | На ребёнка-инвалида |
| 311 | Имущественный вычет (расходы на приобретение) |
| 312 | Имущественный вычет (проценты по ипотеке) |
| 320 | Социальный вычет (обучение) |
| 321 | Социальный вычет (обучение детей) |
| 324 | Социальный вычет (лечение) |
| 325 | Социальный вычет (ДМС) |
| 327 | Социальный вычет (пенсионные взносы) |
| 501 | Вычет из стоимости подарков (до 4 000 руб.) |
| 503 | Вычет из материальной помощи (до 4 000 руб.) |
Что проверять при анализе
Сверка данных
- Совпадение ИНН налогоплательщика между документами
- Корректность налогового периода (
ОтчетГод) - Сходимость:
НалИсчисл=НалУдерж± переплата/задолженность - Полнота месяцев (все 12 месяцев при работе полный год)
- Соответствие ставки налога (13% / 15% / 30% / 35%)
Типичные ошибки
- Расхождение сумм
СумДоходпо месяцам и итоговогоСумДохОбщ - Вычеты превышают допустимый лимит (например, 120 000 руб. для социальных)
- Отсутствие обязательных реквизитов (ИНН, КПП агента)
- Неправильный признак справки (Призн=1 vs Призн=2)
Сравнение 2-НДФЛ и 3-НДФЛ
- Общая сумма дохода в 2-НДФЛ должна совпадать с Приложением 1 в 3-НДФЛ
- Удержанный налог должен совпадать
- Вычеты у агента (2-НДФЛ) + дополнительные вычеты (3-НДФЛ) = итого вычетов
Кодировки
| Формат | Кодировка | Примечание |
|---|---|---|
| Старые файлы ФНС (до ~2019) | windows-1251 | В <?xml encoding="windows-1251"?> |
| Новые файлы ФНС | UTF-8 | Стандарт с 2020+ |
| BOM | UTF-8 BOM (EF BB BF) | Встречается редко |
Система автоматически определяет кодировку по XML-декларации и содержимому файла.
Типичные задачи пользователей
| Вопрос | Что делать |
|---|---|
| «Сколько заработал за год?» | Найти СумДохОбщ или суммировать СумДоход по месяцам |
| «Какие вычеты применены?» | Извлечь <СвВыч> → КодВычет + СумВычет, расшифровать коды |
| «Сходятся ли суммы?» | Проверить СумДохОбщ = сумма по месяцам, НалИсчисл ≈ НалОблБаз × ставка |
| «Есть ли расхождения?» | Сравнить данные 2-НДФЛ и 3-НДФЛ (суммы, вычеты, удержания) |
| «Правильно ли заполнена декларация?» | Проверить обязательные поля, формулы, лимиты вычетов |
Другие XML-документы ФНС
| Тип документа | Корневой элемент | Описание |
|---|---|---|
| Выписка из ЕГРЮЛ | <Файл> → <СвЮЛ> | Сведения о юрлице: название, ИНН, ОГРН, учредители, виды деятельности |
| Выписка из ЕГРИП | <Файл> → <СвИП> | Сведения об ИП: ФИО, ОГРНИП, виды деятельности |
| Требование о предоставлении документов | <Файл> → <Документ> | Перечень запрашиваемых документов, сроки представления |
| Акт сверки | <Файл> → <АктСвworking> | Расчёты по налогам и сборам, задолженности |
УПД в формате ЭДО (счёт-фактура + документ о передаче)
Электронный УПД — это XML-файл обмена по формату ФНС. Генерация УПД разрешена и описана ниже; она подчинена трём жёстким воротам: версия формата, XSD-валидация, арифметическая сверка. Разбор входящего УПД — по тем же правилам, только без записи файла. Конвертация входящего УПД в 5.03 (в том числе с 5.01) — тоже разрешена: она идёт через перенос реквизитов из исходного XML, см. «Источник — уже готовый XML».
Версия формата — только 5.03
| Параметр | Значение |
|---|---|
| Нормативная база | Приказ ФНС России № ЕД-7-26/970@ |
ВерсФорм в <Файл> | 5.03 |
| КНД | 1115131 |
| Префикс имени файла (продавец) | ON_NSCHFDOPPR_ |
| Префикс имени файла (покупатель) | ON_NSCHFDOPPOK_ |
| Кодировка | windows-1251 в XML-декларации и при записи байтов |
- Версия 5.01 запрещена — не генерировать, не «поддерживать для совместимости», не предлагать как запасной вариант. Если пользователь просит 5.01 — объяснить, что действующий формат по приказу ЕД-7-26/970@ это 5.03, и сделать 5.03.
Функцияв<Документ>:СЧФДОП(счёт-фактура + передача),СЧФ(только счёт-фактура),ДОП(только документ о передаче). Значение выбирается из требований задачи и не меняется по ходу генерации.- Перечни допустимых значений (
НалСт,ОКЕИ_Тов, коды видов операций, признаки) берутся из действующей XSD, а не из памяти. Схема — источник истины по enum'ам.
Каркас документа
<Файл ИдФайл="…" ВерсФорм="5.03" ВерсПрог="…">
<Документ КНД="1115131" Функция="СЧФДОП" ДатаИнфПр="…" ВремИнфПр="…" НаимЭконСубСост="…">
<СвСчФакт НомерДок="…" ДатаДок="…">
<СвПрод><ИдСв><СвЮЛУч НаимОрг="…" ИННЮЛ="…" КПП="…"/></ИдСв><Адрес … /></СвПрод>
<СвПокуп><ИдСв><СвЮЛУч НаимОрг="…" ИННЮЛ="…" КПП="…"/></ИдСв><Адрес … /></СвПокуп>
<ДокПодтвОтгр … />
<ДенИзм КодОКВ="643" НаимОКВ="Российский рубль"/>
</СвСчФакт>
<ТаблСчФакт>
<СведТов НомСтр="1" НаимТов="…" ОКЕИ_Тов="796" КолТов="…" ЦенаТов="…"
СтТовБезНДС="…" НалСт="…" СтТовУчНал="…">
<Акциз><БезАкциз>без акциза</БезАкциз></Акциз>
<СумНал><СумНал>…</СумНал></СумНал>
</СведТов>
<ВсегоОпл СтТовБезНДСВсего="…" СтТовУчНалВсего="…">
<СумНалВсего><СумНал>…</СумНал></СумНалВсего>
</ВсегоОпл>
</ТаблСчФакт>
<СвПродПер><СвПер СодОпер="…"><ОснПер … /></СвПер></СвПродПер>
<Подписант СпосПодтПолном="1"><ФИО Фамилия="…" Имя="…" Отчество="…"/></Подписант>
</Документ>
</Файл>
Имена реквизитов в 5.03 отличаются от привычных по 5.01 и от бумажной формы: номер и дата документа — НомерДок/ДатаДок (не НомерСчФ/ДатаСчФ), сумма налога — вложенный <СумНал><СумНал> (элемента СумНалСчФ в схеме нет), валюта — отдельный <ДенИзм> внутри СвСчФакт (не атрибут КодОКВ), участник — <ИдСв><СвЮЛУч> для юрлица и <ИдСв><СвИП> для ИП, <Подписант> обязателен. Проверять по XSD, а не по памяти.
Сборка и валидация — примитивами скила fns_upd_xml_ru (save_upd_xml, validate_upd_xml, rows_to_positions), а не ручной склейкой строк.
Ворота 1 — XSD-валидация обязательна
Результат не отдаётся пользователю, пока файл не прошёл официальную XSD-схему формата 5.03.
from lxml import etree
parser = etree.XMLParser(resolve_entities=False, no_network=True, load_dtd=False)
schema = etree.XMLSchema(etree.parse(xsd_path, parser))
doc = etree.parse(xml_path, parser)
if not schema.validate(doc):
raise ValueError("УПД не прошёл XSD: " + "; ".join(str(e) for e in schema.error_log))
- XML пользователя или контрагента — недоверенный ввод. Любой разбор XML (валидация, конвертация, анализ) идёт только через парсер с
resolve_entities=False, no_network=True, load_dtd=False. Голыйetree.parse(path)/etree.fromstring(payload)запрещён: внешние сущности в присланном файле читают локальные файлы сервера (XXE), а DTD с вложенными сущностями раздувается в отказ обслуживания. - Схема берётся из официального комплекта ФНС для 5.03 (основная схема + подключаемые типы в том же каталоге; относительные
xs:includeломаются при разрозненном копировании файлов). - Валидируется тот самый файл, который уйдёт пользователю: те же байты, та же кодировка, после всех правок.
- XSD недоступна — файл не отдаётся. Сказать прямо: схемы нет, валидация не выполнена, результат не выдан. «Скорее всего валидный» — не результат.
- В ответе указывается, какой схемой прогнали и что валидация прошла.
Ворота 2 — арифметическая сверка
Проверяется до XSD и после любой правки сумм. Все суммы — Decimal, округление до 2 знаков ROUND_HALF_UP, сравнение точное.
По каждой строке:
ЦенаТов × КолТов = СтТовБезНДССтТовБезНДС × ставка = СумНал(значение в<СведТов><СумНал><СумНал>)СтТовБезНДС + СумНал = СтТовУчНал
По документу:
Σ СтТовБезНДС = СтТовБезНДСВсегоΣ СумНал = СумНалВсего/СумНалΣ СтТовУчНал = СтТовУчНалВсего
from decimal import Decimal, ROUND_HALF_UP
def money(value) -> Decimal:
return Decimal(str(value)).quantize(Decimal("0.01"), rounding=ROUND_HALF_UP)
for row in rows:
expected = money(money(row["price"]) * Decimal(str(row["qty"])))
if expected != money(row["sum_no_vat"]):
raise ValueError(
f"строка {row['num']}: цена×количество={expected}, в документе {money(row['sum_no_vat'])}"
)
total = money(sum(money(r["sum_no_vat"]) for r in rows))
if total != money(doc_total):
raise ValueError(f"итог документа {money(doc_total)} != сумма строк {total}")
- Любое расхождение — жёсткая ошибка и остановка: файл не пишется и не отдаётся, пользователю называется строка и обе величины.
- Молча подгонять итог, «размазывать» копейку по строкам, дописывать корректирующую строку или менять исходные данные — запрещено. Расхождение — это вопрос к исходным данным, а не к генератору.
- Исходные суммы из xlsx/CSV не переокругляются «для красоты»: если данные не сходятся сами по себе, об этом сообщается, а не исправляется.
Ворота 3 — единый режим НДС по документу
- Все строки одного УПД идут в одном режиме НДС: либо все со ставкой, либо все «без НДС». Смешивать облагаемые и необлагаемые позиции в одном документе нельзя.
- Ставка
НалСтодинакова для всех строк документа. Разные ставки — разные документы. - Обнаружен смешанный режим во входных данных — жёсткая ошибка с перечислением строк и предложением разбить на отдельные УПД. Не выбирать ставку «по большинству» и не подставлять её молча.
Источник — уже готовый XML: конвертировать, а не пересобирать
Если на входе есть XML-файл документа — свой УПД версии 5.01, файл контрагента, выгрузка из 1С или из личного кабинета оператора — этот файл и есть источник данных. Задача «переложи в 5.03» — это перенос реквизитов, а не новая сборка документа.
- Разобрать входящий XML и перенести значения поэлементно по карте соответствия. Реквизиты, которые есть в файле, берутся из файла: ни из таблицы, ни из памяти, ни повторным вопросом пользователю.
- Пересобирать документ из xlsx/CSV, когда XML уже дан, — запрещено: так теряются реквизиты, которых в таблице нет (ИНН/КПП, адреса, основание передачи, подписант,
ДокПодтвОтгр, номера ГТД, код вида операции). - Номер и дату документа не менять: конвертация версии формата — не новый документ. Меняются только
ВерсФорм,ИдФайл(он привязан к имени нового файла) и имена реквизитов по карте. - Входящий файл не правится: он остаётся байт-в-байт как получен, результат — новый файл 5.03. Запрет «не изменять XML ФНС» — про правку присланного файла на месте, а не про конвертацию в новый.
- Реквизит, обязательный в 5.03, но отсутствующий во входящем документе (в 5.01 части блоков не было) — спросить у пользователя. Заглушки и «типовые» значения не подставлять.
- Расхождение сумм в исходном XML не исправляется молча: сработали те же ворота 2 и 3 — назвать строку и обе величины.
- После переноса — обязательно ворота 2 (арифметика), затем ворота 1 (XSD). Совпадение с исходником по суммам показать пользователю: число позиций, итог без НДС, НДС, итог с НДС до и после конвертации.
Карта соответствия 5.01 → 5.03 (проверять по действующей XSD, она источник истины):
| В 5.01 / в бумажной форме | В 5.03 |
|---|---|
ВерсФорм="5.01" | ВерсФорм="5.03" |
НомерСчФ, ДатаСчФ | НомерДок, ДатаДок |
СвЮЛ | <ИдСв><СвЮЛУч> (ИП — <ИдСв><СвИП> + ФИО) |
<СвТов> | <ТаблСчФакт> → <СведТов> |
СумНал атрибутом, СумНалСчФ | <СумНал><СумНал>…</СумНал></СумНал> |
КодОКВ атрибутом на СвСчФакт | <ДенИзм КодОКВ="643" НаимОКВ="Российский рубль"/> |
НалСт="0%" на необлагаемой позиции | НалСт="без НДС" + <СумНал><БезНДС>без НДС</БезНДС></СумНал> |
| Подписант отсутствовал | <Подписант> обязателен (СпосПодтПолном + ФИО) |
0% и без НДС при переносе не взаимозаменяемы: 0% — экспортная ставка, без НДС — освобождение. Если в исходнике стоит одно, а по смыслу операции нужно другое — спросить, не переставлять самостоятельно.
Порядок отдачи результата
- Собрать данные: из входящего XML, если он есть (см. «Источник — уже готовый XML»), иначе из таблицы. Привести суммы к
Decimal. - Проверить единый режим НДС.
- Провести арифметическую сверку строк и итогов.
- Сформировать XML 5.03 в
windows-1251. - Прогнать XSD.
- Только после успешных 2–5 — сохранить файл и отдать пользователю карточку артефакта, а не текст XML в чат.
Anti-patterns
- Не править присланный XML-файл ФНС или контрагента на месте — он остаётся как получен; конвертация в новый файл 5.03 разрешена и описана выше
- Не пересобирать документ из таблицы, когда на входе уже есть XML — переносить реквизиты из него
- Не отдавать сгенерированный УПД без успешной XSD-валидации и арифметической сверки
- Не генерировать УПД версии 5.01 и не смешивать режимы НДС в одном документе
- Не печатать готовый XML текстом в чат — отдавать файлом
- Не разбирать XML парсером с сущностями и DTD по умолчанию — только
etree.XMLParser(resolve_entities=False, no_network=True, load_dtd=False); это касается и входящих файлов, и собственного результата - Не генерировать прочие XML-форматы ФНС — отчётность и декларации (для них нужны 1С, Контур); УПД, счёт-фактура и ДОП — исключение, они разрешены и описаны выше
- Не давать налоговых консультаций — только анализ данных из документа
- При неуверенности в интерпретации — рекомендовать обращение к налоговому специалисту
Похожие навыки
Попробуйте этот навык
Зарегистрируйтесь и используйте навык «Анализ XML-документов ФНС» бесплатно.