При обмене данными через XML-файлы, особенно при формировании регламентированной отчетности для налоговых органов, программисты часто сталкиваются с жесткими требованиями схем валидации (XSD). Одной из наиболее распространенных проблем является передача «пустого» значения для числовых (decimal) или дат (date) полей. В отличие от строковых типов, где можно просто оставить пустой тег <Tag></Tag>, для числовых типов простая пустота или значение 0,00 часто являются недопустимыми с точки зрения логики учета (например, когда НДС не предусмотрен вовсе, а не равен 0%).
В этой статье мы подробно разберем, как правильно использовать стандарт XML для передачи отсутствующих данных, и рассмотрим реализацию этой задачи в 1С как с помощью низкоуровневой записи XML, так и через механизмы XDTO.
Прежде чем переходить к коду, давайте проанализируем ситуацию с точки зрения теории XML. В схемах XSD для элементов существует атрибут nillable="true". Он указывает на то, что элемент может принимать «пустое» значение (аналог NULL в базах данных). Если в схеме указано, что поле является числовым, то просто оставить его пустым нельзя — валидатор выдаст ошибку, так как пустая строка не является числом. Чтобы легально передать отсутствие значения, используется специальный атрибут xsi:nil="true".
Рассмотрим пример. Если мы передаем нулевой НДС, XML выглядит так:
<Amount>0</Amount>
Но если НДС отсутствует в принципе (например, операция не облагается НДС), и формат требует именно пустое значение, запись должна выглядеть следующим образом:
<Amount xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:nil="true"/>
Использование механизмов XDTO (XML Data Transfer Objects) является наиболее правильным и современным подходом в 1С. Сериализатор XDTO берет на себя всю работу по управлению пространствами имен и правильному формированию атрибутов. Разберем по шагам, как это работает.
Для того чтобы 1С автоматически добавила xsi:nil="true", должны быть соблюдены два условия:
Nillable (Допускает пустое значение).Неопределено.Проанализируем пример кода для записи такого объекта:
// Предположим, у нас есть объект XDTO "ДанныеДокумента"
// Свойство "Налог" имеет тип decimal и nillable = true
Если НалогНеРассчитывается Тогда
ДанныеДокумента.Налог = Неопределено; // Именно Неопределено вызовет запись xsi:nil
Иначе
ДанныеДокумента.Налог = 150.25;
КонецЕсли;
// Записываем объект в файл
Запись = Новый ЗаписьXML;
Запись.ОткрытьФайл("C:\Reports\Invoice.xml");
ФабрикаXDTO.ЗаписатьXML(Запись, ДанныеДокумента);
Запись.Закрыть();
В этом случае система сама добавит объявление пространства имен xmlns:xsi в корень файла и корректно сформирует узел для свойства "Налог".
Иногда возникают ситуации, когда использование XDTO невозможно или избыточно, и программист формирует XML-структуру вручную через ЗаписьXML. В этом случае нам придется самостоятельно управлять атрибутами и пространствами имен. Выясним, как это сделать правильно.
Рассмотрим алгоритм ручной вставки пустого значения:
xsi, соответствующий стандарту XML Schema Instance.Рассмотрим практический пример кода:
ЗаписьXML = Новый ЗаписьXML;
ЗаписьXML.ОткрытьФайл("C:\Reports\ManualReport.xml", "UTF-8");
// Начинаем документ и объявляем пространство имен xsi в корне
ЗаписьXML.ЗаписатьОбъявлениеXML();
ЗаписьXML.ЗаписатьНачалоЭлемента("Root");
ЗаписьXML.ЗаписатьСоответствиеПространстваИмен("xsi", "http://www.w3.org/2001/XMLSchema-instance");
// Записываем обычное числовое поле
ЗаписьXML.ЗаписатьНачалоЭлемента("TaxableValue");
ЗаписьXML.ЗаписатьТекст("40.44");
ЗаписьXML.ЗаписатьКонецЭлемента();
// Записываем "пустое" числовое поле
ЗаписьXML.ЗаписатьНачалоЭлемента("TaxPercentage");
// Важно: записываем атрибут nil с указанием URI!
ЗаписьXML.ЗаписатьАтрибут("nil", "http://www.w3.org/2001/XMLSchema-instance", "true");
ЗаписьXML.ЗаписатьКонецЭлемента(); // Тег закроется как <TaxPercentage xsi:nil="true"/>
ЗаписьXML.ЗаписатьКонецЭлемента(); // Закрываем Root
ЗаписьXML.Закрыть();
Важно не путать две разные настройки в XML-схемах: minOccurs="0" и nillable="true". Проанализируем разницу, так как это часто становится причиной ошибок при сдаче отчетности.
Неопределено при Nillable=false).xsi:nil="true" будет принято корректно.Проблема пустых значений особенно актуальна для дат. В 1С «пустая дата» (01.01.0001) при обычной сериализации часто превращается в строку вида "0001-01-01", что не принимается большинством внешних систем и валидаторов. Использование xsi:nil="true" — единственный универсальный способ передать отсутствие даты в поле типа xsd:date или xsd:dateTime.
При использовании XDTO достаточно убедиться, что свойство в схеме помечено как Nillable, и передать в него Неопределено. Если вы используете ручную запись, следуйте примеру выше, записывая атрибут nil вместо вызова ЗаписатьТекст().
Подведем итоги нашего исследования. Для корректной передачи пустых значений в XML из 1С необходимо:
Неопределено и проверять флаг Nillable в пакете."nil" с пространством имен "http://www.w3.org/2001/XMLSchema-instance".Соблюдение этих правил позволит вам создавать надежные механизмы обмена данными, которые успешно пройдут любую автоматическую проверку. При необходимости можно использовать обработку для проверки валидности готового XML-файла по схеме XSD или пакету XDTO.