Программное создание xml (а можно и HTML) на основе xml схемы (XSD), через фабрику XDTO






Объект XDTO, Фабрика XDTO, ПакетXDTO — как же это все сложно, или нет?

Warning

Данная статья не претендует на оригинальность и не является конечным решением.

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

 

Разработчику решений на 1С, какова не была бы его судьба, рано или поздно все равно придется иметь дело с XDTO. Самое простое это считать XML:

// прочитали
ЧтениеXML = Новый ЧтениеXML;
ЧтениеXML.УстановитьСтроку(XMLСтрока);
ОбъектXDTO = ФабрикаXDTO.ПрочитатьXML(ЧтениеXML);
ЧтениеXML.Закрыть();

Теперь ко всем элементам и атрибутам можно обращаться через точку, где объект XDTO приблизительно представляет собой структуру из массивов и структур.

Неплохо. Но как этот самый объект построить с нуля и записать? Об этом и пойдет речь ниже!

План для построения Объекта XDTO с нуля:

  1. XML схема, она же XSD.
  2. Загрузить ее в фабрику XDTO;
  3. Получить комплексный тип корневого элемента;
  4. Создать новый ОбъектXDTO;
  5. Инициализировать его свойства (и свойства его свойств);
  6. Заполнить объект xdto;
  7. Преобразовать в строку XML.

Демонстрационная реализация на основе построения HTML для вывода таблицы значений:

Xml схема набросанная в oxygen xml editor:

<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:tns="http://htmlbook.ru/html" xmlns:xs="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://htmlbook.ru/html" attributeFormDefault="unqualified"
elementFormDefault="qualified" xmlns:vc="http://www.w3.org/2007/XMLSchema-versioning">
<xs:attributeGroup name="MetaValue">
<xs:attribute name="charset" type="xs:string"/>
<xs:attribute name="content" type="xs:string"/>
</xs:attributeGroup>
<xs:element name="BODY">
<xs:complexType>
<xs:sequence>
<xs:any namespace="##any"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="HEAD">
<xs:complexType>
<xs:sequence>
<xs:element maxOccurs="unbounded" minOccurs="0" name="meta">
<xs:complexType>
<xs:attributeGroup ref="tns:MetaValue"/>
</xs:complexType>
</xs:element>
<xs:element minOccurs="0" name="Title" type="xs:string"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:complexType name="Table">
<xs:sequence>
<xs:element name="Caption" type="xs:string"/>
<xs:element name="TR" maxOccurs="unbounded" minOccurs="0">
<xs:complexType>
<xs:sequence>
<xs:element name="TH" minOccurs="0" maxOccurs="unbounded" type="xs:string"> </xs:element>
<xs:element name="TD" minOccurs="0" maxOccurs="unbounded" type="xs:string">
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
<xs:attribute default="1" name="border"/>
</xs:complexType>
<xs:complexType name="HTML">
<xs:sequence>
<xs:element ref="tns:HEAD"> </xs:element>
<xs:element ref="tns:BODY"/>
</xs:sequence>
</xs:complexType>
</xs:schema>
 

 Визуальное представление схемы:

Код конструктора:

&НаСервереБезКонтекста
Функция ОбъектXDTOВXML(ОбъектXDTO, Фабрика)
ЗаписьXML = Новый ЗаписьXML;
ЗаписьXML.УстановитьСтроку("UTF-8");
Фабрика.ЗаписатьXML(ЗаписьXML, ОбъектXDTO);
Возврат ЗаписьXML.Закрыть();
КонецФункции

&НаСервере
Функция ПолучитьТипСвойтваXDTO(ОбъектXDTO, ИмяСвойтва)
Возврат ОбъектXDTO.Свойства().Получить(ИмяСвойтва).Тип;
КонецФункции

&НаСервере
Функция ИнициализироватьСвойствоXDTO(ОбъектXDTO, Фабрика, ИмяСвойтва) Экспорт

ТипСвойтваXDTO = ПолучитьТипСвойтваXDTO(ОбъектXDTO, ИмяСвойтва);
Если ТипСвойтваXDTO <> Неопределено Тогда
ОбъектXDTO[ИмяСвойтва] = Фабрика.Создать(ТипСвойтваXDTO);
Возврат ОбъектXDTO[ИмяСвойтва];
Иначе
Возврат Неопределено;
КонецЕсли;

КонецФункции

&НаСервере
Функция ТаблицуЗначенийВHTML(ТаблицаДанных)

// файл для загрзки xml схемы
ИмяВременногоФайла = ПолучитьИмяВременногоФайла("XSD");
// запишем содержимое схемы
РеквизитФормыВзначение("Объект").ПолучитьМакет("html_xsd").Записать(ИмяВременногоФайла, "utf-8");
// новая фабрика с импортированной схемой
Фабрика = СоздатьФабрикуXDTO(ИмяВременногоФайла);
// если схема была импортирована в конфигурацию как пакет XDTO то код выше ненужен.
// достаточно лишь фабрика = ФабрикаXDTO;

// новый пустой xdto
ОбъектHTML = Фабрика.Создать(Фабрика.Тип("http://htmlbook.ru/html", "HTML"));
// получить тиип head
ОбъектHead = ИнициализироватьСвойствоXDTO(ОбъектHTML, Фабрика, "head");
// установим описание страницы
ОбъектHead.Title = "ТаблицаДанных";
// элемент списка meta
ТипЭлементаMeta = ПолучитьТипСвойтваXDTO(ОбъектHead, "meta");
// создать элемент meta
ОбъектMeta = Фабрика.Создать(ТипЭлементаMeta);
// установим кодировку html
ОбъектMeta.charset = "UTF-8";
// добавить элемент в список
ОбъектHead.Meta.Добавить(ОбъектMeta);
// получим объект body
ОбъектBody = ИнициализироватьСвойствоXDTO(ОбъектHTML, Фабрика, "body");
// создать таблицу
ОбъектTable = Фабрика.Создать(Фабрика.Тип("http://htmlbook.ru/html", "Table"));
// добавить таблицу в body
ОбъектBody.Добавить(ФормаXML.Элемент, "http://htmlbook.ru/html", "Table", ОбъектTable);
// зададим имя таблици
ОбъектTable.Caption = "ТаблицаДанных";
// установим границу между ячейками
ОбъектTable.Border = "1";

// получим базовые типы списков
ТипTR = ПолучитьТипСвойтваXDTO(ОбъектTable, "tr");
ОбъектTR = Фабрика.Создать(ТипTR);
ТипTD = ПолучитьТипСвойтваXDTO(ОбъектTR, "td");
ТипTH = ПолучитьТипСвойтваXDTO(ОбъектTR, "th");

// установим имена колонок
ОбъектTable.TR.Добавить(ОбъектTR);
Для Каждого КолонкаТаблицы Из ТаблицаДанных.Колонки Цикл
ОбъектTH = Фабрика.Создать(ТипTH, КолонкаТаблицы.Имя);
ОбъектTR.TH.Добавить(ОбъектTH);
КонецЦикла;

// установим значения строк
Для Каждого СтрокаТаблицы Из ТаблицаДанных Цикл
ОбъектTR = Фабрика.Создать(ТипTR);
ОбъектTable.TR.Добавить(ОбъектTR);
Для Каждого ЯчейкаТаблици Из СтрокаТаблицы Цикл
ОбъектTD = Фабрика.Создать(ТипTD, Строка(ЯчейкаТаблици));
ОбъектTR.TD.Добавить(ОбъектTD);
КонецЦикла;
КонецЦикла;

// выполнить валидацию
Попытка
ОбъектHTML.Проверить();
Исключение
Сообщить(ПодробноеПредставлениеОшибки(ИнформацияОбОшибке()));
КонецПопытки;

Возврат ОбъектXDTOВXML(ОбъектHTML, Фабрика);

КонецФункции

Сразу отвечу на вопрос, в чем заключается разница между пакетом XDTO и XML схемой? Если речь идет о создании объекта XDTO, то разницы нет, внешнюю схему, в отличие от пакета, изменять и сохранять проще.

Плюсы данного подхода:

  • Можно взять одну или несколько XSD Схем, подкорректировать под 1С и строить XML;
  • Можно стоить простые html странички;
  • Валидация — использование схемы, дает куда больше шансов, что во время разработки программист не забудет какой- нибудь тег или атрибут. 

 

11 Comments

  1. veri123

    Автор перевернул мой взгляд на мир.

    Долго думал как оно работает.

    Осознал что html от xml отличается только тем что теги фиксированы.

    Reply
  2. awk
    Сразу отвечу на вопрос, в чем заключается разница между пакетом XDTO и XML схемой?

    Если хотите использовать аннотации, например для автогенерации документации (xsddoc), то забудьте про XDTO.

    Reply
  3. awk

    (2) Не только. В html незакрытые теги (<p>< br ></p>) использовать можно, а в xml нельзя

    Reply
  4. starik-2005

    (1) да ничего там в этом ХДТО нет такого — просто объектная модель XML. Схема определяет совокупность объектов и их свойств. Сами объекты ХДТО могут содержать другие объекты в качестве свойств полей. Я как-то писал о том, как можно загрузить XML в дерево значений или выгрузить иерархический справочник в XML — вот там как раз все через ХДТО.

    Reply
  5. starik-2005

    (2)

    Осознал что html от xml отличается только тем что теги фиксированы.

    В html необязательно закрывать тег, потому html не всегда можно прочитать в фабрику — придется его немного покромсать, о чем я тоже как-то писал.

    Reply
  6. ntemny

    Автору. Вообще xml в html проще и быстрее через ПреобразованиеXSL делать. Достаточно сериализовать объект а потом через преобразование выдать в html строку.

    Reply
  7. Evil Beaver

    Привести вам ссылки на мои 3 статьи по XDTO или не надо? 😀

    Reply
  8. Evil Beaver

    (2)

    Осознал что html от xml отличается только тем что теги фиксированы.

    НЕЕТ! Отличаются смыслом и наполнением! А за теги html, написанные КАПСЛОКОМ автору — порицание и бесплатная путевка в 2019 год из его 1999-го!

    Reply
  9. Eret1k

    (8) Infostart уникальная площадка для того, чтобы делиться опытом.

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

    P.S. Прочитал статьи 3, круто.

    Reply
  10. caponid

    (8) Не надо, они и так есть в закладках))

    А вот эта статья очень понравилась как легкостью изложения, так и изящностью идеи примера.

    Автору респект.

    Reply
  11. rudnitskij
    Функция ОбъектXDTOВXML(ОбъектXDTO, Фабрика)

    Мне одному кажется, что имя этой же функции в виде

    ОбъектXDTO_В_XML

    было бы более наглядным и легче читаемым?

    Reply

Leave a Comment

Ваш адрес email не будет опубликован. Обязательные поля помечены *