Как преобразовать файл c контентом XLS в XML формат?

В зависимости от требований к механике импорта контента сайт/программа покупателя может не поддерживать формат документов XLS не взирая на сложность структуры данных. Для приведения файла к соответствующему виду и структуре применяем открытый пакет LibreOffice или Apache OpenOffice (для преобразования в CSV подойдут оба и окна одинаковые, для преобразования в XML рекомендуется второй вариант). Ниже представлены варианты, как преобразовать данные из документа XLS в нужный вид.


Скачиваем контент в XLS

  1. Формируем выборку. Выгрузка с сайта ограничена 1500 позициями за раз, так что рекомендуется скачивать контент в несколько итераций. Для этого необходимо либо воспользоваться фильтрами из правой колонки, либо зайти в категорию. Цель: при ограничении выборки список товаров должен иметь не более 93 страниц включительно при отображении "16 товаров на страницу" в селекторе товаров
  2. Скачиваем документ нажав кнопку Скачать контент в XLS
  3. Открываем документ в libreOffice.

Для начала определяем, в каком виде нужен документ и зачем? от этого зависит - употребит ли документ целевая система или нет.

В какой формат преобразовывать?

Что такое XML, чем он отличается от YML, KML и других подобных форматов данных.

И YML, и KML и даже HTML можно интерпретировать, как XML, ведь по сути они являются языками одного семейства SGML. XML предназначался, как свободно расширяемый язык для передачи структурированных данных, достаточно понятный как людям, так и машинам, когда в период бурного развития Web вылезла боком ограниченность HTML. Но и HTML и KML и YML объединяет то, что вне зависимости от своего предназначения, в каждом из трёх есть известный набор тегов со своими параметрами и требованиями к содержанию. У XML ограничения в тегах и их комбинировании нет, есть лишь ограничения в синтаксисе языка, таким образом с помощью алгоритма формирующего данные в формате XML-документа, можно создать любой из выше перечисленных документов, просто имея понимание, какой вид каждого поля нужен программе, что будет принимать на вход этот файл.

Преобразование в структуру XML

Табличный документ можно преобразовать в XML дерево данных, для систем, что требуют сразу структурированные данные. Однако требования для реализации подобной задачи намного выше, чем просто взять и сохранить файл в нужном формате и с необходимым разделителем (ведь XML сам по себе не знает, в каком виде нужны данные на выходе). Ниже будет описан метод создания механизма, позволяющего создать XML при помощи Apache OpenOffice и созданного шаблона XSLT (он описывает структуру получаемого документа).

Для реализации этого метода необходимо "объяснить" программе, какие данные и в каком виде вносить. Для этой цели и существует XSLT-файл. Он в сути себя "трафарет", на заготовленные места которого выводятся данные. Впрочем, алгоритм действий по-порядку:

  1. Скачиваем файл XLS
  2. Определяем те данные, что нужны в выходном файле
  3. Создаём образцовый XML выходного файла, который бы получился имей таблица всего одну строку с информацией
  4. Копируем образец XML сохраняя его с расширением *.xsl
  5. Создаём "Фильтр XML"
  6. Подключаем xsl файл, как фильтр экспорта
  7. Проверяем возможность экспорта в данный формат.
  8. Заменяем статичные конструкции макросами.
  9. Проверяем работоспособность получившегося модуля.
  10. Исправляем ошибки.
  11. Повторяем предыдущие два пункта.

Основные структуры и конструкции в XSLT

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

Подробная информация о шаблонах XSLT доступна по ссылке ниже, а в данной инструкции будут рассмотрены только базовые элементы в той форме, в которой они применяются для данной задачи:
https://xsltdev.ru/xslt/

Заголовок файла XSLT

Пример:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0"
xmlns:table="urn:oasis:names:tc:opendocument:xmlns:table:1.0"
xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0"
xmlns:meta="urn:oasis:names:tc:opendocument:xmlns:meta:1.0"
exclude-result-prefixes="office table text meta">
<xsl:output method = "xml" indent = "yes" encoding = "UTF-8" omit-xml-declaration = "no" doctype-system="shops.dtd"/>

С подобного текста начинаются все файлы XSLT. Первая строка хранит в себе информацию о версии документа (1.0) и его кодировке (UTF-8).
Корневым элементом XSLT-документа всегда является элемент xsl:stylesheet .
Строки с третьей по седьмую отвечают за подключение данных из документа OpenOffice в соответствующие переменные. Рекомендуется оставить эту всю конструкцию как есть в шаблоне файла.

Элемент xsl:output позволяет указывать, каким образом должно быть выведено результирующее дерево.
Атрибут method указывает, каким образом будет выводиться выходной документ. В текущем разборе используется метод вывода "xml", однако доступны такие методы, как "html" и "text".
Атрибут indent включает или выключает отступы. Без отступов файл будет занимать меньше памяти, но удобен только для машинной обработки. С отступами файл будет занимать больше места из-за большого количества пробельных знаков и переносов строки, но при этом неоспоримым плюсом будет возможность проанализировать его вручную. Может принимать значения "yes" или "no".
Атрибут encoding указывает кодировку выходного файла. Этот параметр должен совпадать с указанным в первой строке. В противном случае - имеем шанс получить "кракозябры".
Атрибут omit-xml-declaration определяет, нужно ли включать декларацию XML (первая строка) в выходящий документ или нет. Значением этого атрибута должно быть либо "yes" (пропустить декларацию), либо "no" (включить декларацию в выходящий документ).
Атрибут doctype-system определяет системный идентификатор, который должен быть использован в декларации типа документа (DTD).

<xsl:template match="table:table">

Элемент верхнего уровня xsl:template определяет в преобразовании шаблонное правило, или просто шаблон.
Атрибут match задает паттерн — образец узлов дерева, для преобразования которых следует применять этот шаблон. В нашем случае он подключается к блоку "table", чтобы можно было получать данные из таблицы.

<xsl:attribute name="date">0000-01-01 00:00:00</xsl:attribute>

Элемент xsl:attribute добавляет в текущий элемент дерева XML атрибут.
Атрибут name задает название атрибута, а в тело тега вносится его значение.

<xsl:variable name="name1" select=""/>

Элемент xsl:element добавляет в текущий элемент дерева XML вложенный элемент.
Атрибут name задает название элемента, а в тело тега вносится его значение.

<xsl:element name="name1">"ЗНАЧЕНИЕ ЭЛЕМЕНТА"</xsl:element>

Элемент xsl:variable используется для создания переменных.
Атрибут name задает имя переменной, а select принимает присваемое переменной значение.

<xsl:if test="Выражение">
<!-- Выполняемые действия -->
</xsl:if;>

Элемент xsl:if позволяет создавать простые условия типа "если-то".

<xsl:for-each select="Переменная-массив">
<!-- содержимое (xsl:sort*, шаблон) -->
</xsl:for-each;>

Элемент xsl:for-each позволяет создавать циклы с перебором массивов.

<xsl:when test="Выражение">
<!-- Выполняемые действия -->
</xsl:when>

Элемент xsl:when позволяет создавать циклы с условным оператором.

Дополнительные данные можно найти по ссылкам ниже:

Механизмы адресации в XSLT или "Как сказать, что куда вставлять?"

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

Скачать контент в XLS.

Ниже пример таблицы:

Номер столбцаНазвание столбца в документеПример заполнения
1 Артикул CLK-G01201
2 Наименование Детский ночник-игрушка Click "Hічні звірятка" Медведь 11 см
3 Вариант Медвежонок
4 Бренд Click
5 Тип товара игрушка
6 Статус Хит продаж!
7 Короткое описание Дитячий нічник іграшка Ведмедик серії Нічні звірятка вироблений під ТМ Click, український бренд дитячої безпечної електроніки. Дитячий нічник Ведмедик має 7 м'яких кольорів світіння, що перемикаються легким хлопком по поверхні. Ведмедик не нагрівається, тому мала дитина може взяти іграшку з собою прям в ліжечко. Дитячий нічник - безпровідний, з вбудованим акумулятором. Заряду вистачить на 20 годин, тобто десь на 3 ночі. Дитячий світильник зроблений з м'якого харчового силікону без шкідливих речовин, тому ведмедика можна м'яти, тискати, розтягувати і навіть кусати! Насадку, що забруднилась, можна легко зняти і випрати в пральній машинці.
8 Описание Детский ночник игрушка Медведь серии Ночные зверята произведен под ТМ Click, украинским брендом детской безопасной электроники. Детский силиконовый светильник имеет 7 приятных мягких цветов свечения для спокойного ночного сна. Ночник силиконовый Мишка не нагревается, поэтому маленький ребенок может взять игрушку с собой прям в кроватку. Мягкий свет детского силиконового ночника создаст уютную распологающую ко сну обстановку. Цвет можно переключить легким хлопком, поэтому даже совсем маленький ребенок без труда справится с этой задачей. Детский ночник - беспроводной, со встроенным аккумулятором. Заряда хватит на 20 часов, то есть где-то на 3 ночи. Детский светильник сделан из пищевого силикона без вредных веществ, из такого силикона изготавливается посуда для малышей.

Силиконовый ночник медвежонок ТМ Click - отличный друг для детей. Дизайн в виде милого животного не оставит равнодушными ни ребёнка, ни его родителей. Нежный мягенький силиконовый плафон детского ночничка не содержит вредных веществ, травмобезопасен для ребёнка, так что его можно мять, тискать, растягивать и даже кусать! Детский ночничок очень лёгкий и совершенно не боится падений. Испачкавшийся силиконовый плафон можно легко снять с детского ночника и помыть в мыльном растворе или постирать в стиральной машинке в режиме деликатной стирки.

Детский силиконовый ночничок имеет в себе 4 режима работы и 7 различных мягких цветов. Можно выбрать как успокаивающий тёплый свет, который помогает уснуть ребенку, так и заставить его переливаться различными цветами, или же пульсировать каким-то одним выбранным светом играя с ним.

Сам силиконовый светильник работает на качественных светодиодах, которые не нагреваются и дают как тёплый мягкий свет, так и могут переливаться различными цветами радуги. Встроенный Li-Ion аккумулятор питает детский силиконовый ночник до 20 часов. Зарядить силиконовый ночник Медвежонка можно от любого USB-порта, будь то зарядное устройство от смартфона, повербанк, ноутбук или USB-порт в автомагнитоле. Чтобы зарядить детский силиконовый ночник к зарядному кабелю необходим будет адаптер 220В-USB 5В 0,5 А или для зарядки так же можно использовать устройство для смартфона с MicroUSB штекером. За два часа силиконовый светильник полностью заряжается и снова готов радовать маленького обладателя. Имея такие возможности, мягкий ночник для ребенка можно брать с собой в любое место и время. Ведь зарядки хватит не на одну ночь. Силиконовый ночник детский Click Медведь (ночные зверята) 11 см, мягкий силиконовый ночник детский в виде милого медведя ТМ Click, можно купить в Украине с официальной гарантией.
9 Особенности Ночник игрушка в виде милого животного
Помогает малышу побороть страх темноты
Не нагревается
Безопасный для малыша (можно кусать)
Мягкий качественый силикон
Можно стирать в машинке
Безопасная конструкция
7 режимов подсветки
4 режима работы
Сенсорный, переключение режимов лёгким хлопком
Около 3 ночей на одном заряде (до 20 часов работы)
Беспроводной детский ночник со встроенным аккумулятором
Работает как от USB, так и от аккумулятора
Заряжается всего за два часа
10 Характеристики Тип: Ночник-игрушка детский
Класс: Силиконовый светильник светодиодный
Вид: Ночник силиконовый Медвеженок
Источник света: RGB-светодиоды
Максимальная мощность: 0,35 Вт
Время работы: 15 - 20 ч
Время зарядки: 90 - 120 мин
Питание: Аккумулятор Li-ion 3,7 В 700мАч (встроенный)
Зарядка: USB 5 В 0,5 А (без QuickCharge)
Режимы работы: 7 режимов подсветки, 4 режима работы
Переключение режимов: Сенсорное (хлопком)
Материал: Мягкий силикон
Размеры модели: 100х92х109 мм
Вес модели: 120 г
11 Подробные характеристики Ночники:
Производитель: Click
Тип: Силиконовые ночники
Питание: От аккумулятора
Материал корпуса: Силикон
Категория: Для девочек; Для мальчиков
Выключатель: На корпусе; Сенсорный
Таймер выключения: Без таймера
Индикатор зарядки: С индикатором
Страна-производитель товара: Китай
Страна регистрации бренда: Украина
Гарантия: 6 месяцев
Тип источника света: Светодиодные (LED)
Цвет корпуса: Белый
Комплектация: Ночник - 1 шт
Кабель USB-MicroUSB - 1 шт
Инструкция - 1 шт
Размеры: 100х92х109 мм
Мощность: 0.3 Вт
12 Комплектация Ночник - 1 шт
Кабель USB-MicroUSB - 1 шт
Инструкция - 1 шт
13 Дополнительно необходимо Всё необходимое есть в комплекте.
14 Сведения о товаре Страна производства: Китай
Рекомендованный возраст: 3+
Материалы: гума, пластик нетокс, метал
Гарантия: 6 місяців. Зберігайте етикетку.
Единица измерения: 1 шт
Срок хранения: 5 років.
Содержит литиевый аккумулятор: Так
Тип упаковки: Виндоу бокс
Вес с упаковкой: 0,177 кг
Размеры упаковки: 12,5х11х9,5 см
Объём упаковки: 0,0013 м. куб.
Количество в ящике: 50 шт
Вес ящика: 10,2 кг
Размеры ящика: 56х49х27 см
Объём ящика: 0,0741 м. куб.
Условия хранения: у відключеному стані; із зарядом 40-60%; подалі від вогню; прямих сонячних променів, вологи; при t -10~+30°C; у місці, захищеному від дітей певного віку.
Предупреждение: Не призначено для дітей віком до 3 років: небезпека задушення дрібними частинами! Ви користовуй під наглядом дорослих. Дріт та пакування не призначені для гри. Зарядка згідно рекоменд. часу
Инструкция: Увімкніть, перемкніть колір. Використовуйте за призначенням. Прати насадку у мильному розчині.
15 Фото http://distributions.com.ua/pictures/5d839a2c05f1243886006580/CLK-G01201_01-original.jpg
http://distributions.com.ua/pictures/5ecfc37705f124491a00603e/CLK-G01201_02-original.jpg
http://distributions.com.ua/pictures/5d84f7ed05f124388600678e/CLK-G01201_03-original.jpg
http://distributions.com.ua/pictures/5d84f7ed05f124388600678f/CLK-G01201_04-original.jpg
http://distributions.com.ua/pictures/5d84f7ed05f1243886006790/CLK-G01201_05-original.jpg
http://distributions.com.ua/pictures/5d84f7ed05f1243886006791/CLK-G01201_06-original.jpg
http://distributions.com.ua/pictures/5d84f7ed05f1243886006792/CLK-G01201_07-original.jpg
http://distributions.com.ua/pictures/5d84f7ed05f1243886006793/CLK-G01201_08m-original.jpg
http://distributions.com.ua/pictures/5d84f7ed05f1243886006794/CLK-G01201_09m-original.jpg
http://distributions.com.ua/pictures/5ebaaac305f124551100029d/CLK-G01201_10-original.jpg
http://distributions.com.ua/pictures/5ebaaac305f124551100029e/CLK-G01201_11m-original.jpg
16 Видео <iframe width="560" height="315" src="//www.youtube.com/embed/KmfVCqARQv0" frameborder="0" allowfullscreen></iframe>
17 Категория Развивающие игрушки / Для маленьких / Ночники
18 Ключевые слова ночник детский, ночник детский купить, купить ночник детский, ночник для детей, купити ночник дитячий, ночник в детскую, ночник на батарейке, ночник для новорожденного, светильник ночник детский, силиконовый ночник, силиконовый ночник купить, ночник силиконовый, ночник единорог, ночник медведь, силиконовый led ночник лампа мишка, ночник зайчик силиконовый, ночник для ребенка, ночник на аккумуляторе, светильник единорог, силиконовый светильник, детский светильник, силиконовый ночник оптом, мягкий силиконовый ночник, силиконовый led ночник лампа, подарок любимой, подарок на День Святого Валентина, подарок на 8 марта, что подарить девушке, что подарить ребенку
19 Meta description

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

Создаём шаблон:

Первым делом создаём файл, который будет хранить наш шаблон. Я назвал его "DD_XML_EXPORT_TEMPLATE.xsl" (назвать файл можно как угодно в пределах требований операционной системы вашего ПК, но расширение обязательно .XSL). На этом этапе это просто пустой документ. Заполнять мы его будем дальше, а сейчас просто поясним программе OpenOffice Calc, что ей надо будет использовать этот файл, как шаблон при экспорте в созданный нами формат.

Экспорт OpenOffice в XML-файл (изображение 1)

Теперь в OpenOffice Calc переходим в меню Сервис/Настройка фильтров XML... и создаём профиль экспорта. Да, экспорта, а не сохранения, т. к. мы создаём совсем свой формат документа. Получаем список поддерживаемых форматов файлов (на скриншоте профиль уже создан, а нам надо его ещё только создать). Нажимаем кнопку "Создать".

Экспорт OpenOffice в XML-файл (изображение 2)

Нам открывается окно в котором мы описываем то, как называется наш "новый формат" документа и теперь стоит задача его заполнить. Заполняем имя фильтра (используется в списке с предыдущей иллюстрации). Указываем в выпадающем списке, что работать этот фильтр будет с табличным редактором "OpenOffice Calc (.ods)". Указываем подсказку к типу файла в диалоге сохранения, например "DD XML". И в завершение этого этапа указываем расширение файла "xml". Т. к. вывод файла у нас будет иметь структуру соответствующую языку разметки XML, то и расширение я ввёл соответствующее. Также надо об этом задуматься по той причине, что у ряда механизмов импорта стоит фильтр на попытки скормить им файл с неверным типом.

Экспорт OpenOffice в XML-файл (изображение 3)

Что же, профиль экспорта мы заполнили, теперь надо объяснить программе, что при экспорте в формат "DD XML (*.xml)" мы хотим, чтоб OpenOffice руководствовался шаблоном, документ которого мы создали. Переходим на вкладку трансформация и в указании "XSLT для экспорта" указываем путь к созданному ранее файлу шаблона. Желательно конечно его хранить вместе с подобными (C:\Program Files (x86)\OpenOffice 4\share\xslt\export\"формат файла"\шаблон.xsl), но для примера я его просто кинул в директорию поближе к корню диска.

Экспорт OpenOffice в XML-файл (изображение 4)

Ура! Теперь при экспорте табличного документа OpenOffice будет предлагать нам сохранить его в нашем формате! Проверить, что формат доступен можно в меню "Файл\Экспорт..."

Пора писать код!

С помощью текстового редактора c подсветкой синтаксиса (Notepad++, Atom, VSCode, jEdit или аналог) открываем созданный ранее файл. И добавляем в него шапку.

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <!-- Добавляем цепочки импорта -->
  3. <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  4. xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0"
  5. xmlns:table="urn:oasis:names:tc:opendocument:xmlns:table:1.0"
  6. xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0"
  7. xmlns:meta="urn:oasis:names:tc:opendocument:xmlns:meta:1.0"
  8. exclude-result-prefixes="office table text meta">
  9. <xsl:output method = "xml" indent = "yes" encoding = "UTF-8" omit-xml-declaration = "no" doctype-system="shops.dtd" />
  10. </xsl:stylesheet>

Далее перед закрывающим тегом </xsl:stylesheet> добавляем "шаблон" с параметром match - равным корневому параметру. Далее будем его называть входным шаблоном.

  1. <xsl:template match="/">
  2. </xsl:template>

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

Экспорт OpenOffice в XML-файл (изображение 5)

Для примера будем рассматривать за основу YML-документ, собственно из него и возьмём костяк. Его код будет ниже с комментариями, что находится где находится и как.

  1. <yml_catalog date="2020-12-31">
  2. <shop>
  3. <!-- Свойства магазина -->
  4. <agency>Мой магазин</agency>
  5. <company>ЧП Иванов</company>
  6. <email>mail@myshop.ua</email>
  7. <name>Мой магазин</name>
  8. <platfrom/>
  9. <url>https://myshop.com.ua</url>
  10. <version>1</version>
  11. <offers>
  12. <!-- Перечень товаров -->
  13. <offer>
  14. <!-- Карточка отдельного товара -->
  15. </offer>
  16. </offers>
  17. </shop>
  18. </yml_catalog>

Для начала у нас есть корневой тег <yml_catalog> у которого есть атрибут "date", в котором хранится дата сохранения. Внутри него есть тег <shop> - который отделяет информацию об одном отдельном магазине. Внутри этого тега есть данные о самом магазине и есть список из товаров в теге <offers>. Каждый отдельный товар находится в своём теге <offer>, но об этом мы будем говорить, когда дело дойдёт именно до описания карточки каждого отдельного товара. На текущий момент у нас есть основа выходного файла. Проверяем, что всё выводится как надо, и далее пробуем наполнять эту структуру данными.

Параметры магазина

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

  1. <!-- Добавляем поля из пользовательских свойств документа -->
  2. <xsl:if test="//meta:user-defined/@meta:name">
  3. <xsl:for-each select="//meta:user-defined">
  4. <xsl:variable name="propertyData" select="@meta:name" />
  5. <xsl:element name="{$propertyData}"><xsl:value-of select="."/></xsl:element>
  6. </xsl:for-each>
  7. </xsl:if>

Экспорт OpenOffice в XML-файл (изображение 6)

У формата OpenDocument есть набор свойств документа, или как в оригинальной документации указано, метаданных. Они описывают все данные об авторе документа, дате создания и последнего изменения, а также произвольные данные. Вот этой функцией мы и воспользовались. Код выше получает из блока метаданных раздел пользовательских и далее создаёт для каждого свойства свой тег, внутрь которого помещает значение этого свойства. Таким образом для того, чтоб изменить какое-либо свойство из набора - нужно просто зайти в свойства документа и сделать правку. Снимок слева отображает данные, которые были бы введены в свойства документа, чтоб получить текст такой же, как и в шаблоне документа описанном ранее. Но указывать можно произвольный набор полей.

А теперь самое весёлое - разбираем табличку!

Для начала в входном шаблоне пропишем ссылку на шаблон обрабатывающий таблицу. Для этого внутрь тега <offers> вставляем код:

<xsl:apply-templates select="//table:table"/>

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

  1. <xsl:template match="table:table">
  2. <xsl:for-each select="table:table-row">
  3. <xsl:variable name="rowIdx" select="position()"/>
  4. <!-- Перебираем строки начиная со второй -->
  5. <xsl:if test="$rowIdx>1">
  6. <offer>
  7. <xsl:for-each select="table:table-cell">
  8. <xsl:variable name="colIdx" select="position()"/>
  9. <xsl:choose>
  10. <!-- Наборы инструкций которые будут создавать отдельный товар -->
  11. </xsl:choose>
  12. </xsl:for-each>
  13. </offer>
  14. </xsl:if>
  15. </xsl:for-each>
  16. </xsl:template>

Данный шаблон - это классический обход массива массивов. Если говорить терминами объектно-ориентированного программирования, таблица - это массив объектов типа "строка", а каждый объект типа "строка" - массив объектов типа "ячейка". Проведём аналогию с книжной полкой на которой стоит сборник томиков Артура Конан-Дойля. Для того, чтоб прочитать информацию с третьего томика на 86-й странице, нужно сначала взять книгу №3, открыть её и пролистать до 86-й страницы. Сначала идёт перебор строк ("томиков"). Начиная со второй строки, каждая строка перебирается по ячейкам. Если порядковый номер ячейки или название столбца проходит по условию - берём содержимое этой ячейки и определённым образом обрабатываем. Ниже мы разберём основную конструкцию для выбора и два основных варианта определить, что делать с полученным элементом, то есть два основных метода адресации.

<xsl:when test="Выражение">
<!-- Выполняемые действия -->
</xsl:when>

When - индексное условие для инструкции селектора choose, некий аналог switch-case из более широко известных языков программирования. В отличие от стандартного case -условия, в when - условия можно комбинировать, как в обычном условном операторе с помощью инструкций OR (или), AND (и) и NOT (не).

Виды адресации

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

Адресация по номеру столбца

Как говорилось ранее - просто вбиваем номер столбца считая от 1 слева-направо. Если информация хранится в нескольких столбцах перебираем все через OR (или). Выглядит это следующим образом:

<xsl:when test="$colIdx=15">
<!-- Выполняемые действия только для столбца №15 -->
</xsl:when>

Или

<xsl:when test="$colIdx=10 or $colIdx=14">
<!-- Выполняемые действия для столбцов №10 и №14 -->
</xsl:when>

Если столбцы расположены рядом, то можно задать диапазон значками "больше", "меньше", "больше или равно", "меньше или равно", указав набор условий через "И".

<xsl:when test="$colIdx>10 and $colIdx<=14">
<!-- Выполняемые действия для столбцов №11, 12, 13 и 14 -->
</xsl:when>

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

Параметрическая адресация или же адресация по "индексной строке".

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

  1. Порядок столбцов не важен от слова "совсем".
  2. Если во входном документе добавился новый столбец - шаблон править не нужно.
  3. Шаблон становится более понятным и лёгким в редактировании.
  4. Можно изменять наполнение выходного файла в соответствии с желаниями пользователя без правки кода шаблона.

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

<xsl:variable name="colName" select="//table:table/table:table-row[1]/table:table-cell[$colIdx]/text:p/text()" />

Дальше используем сравнение строковых констант, которые можно собирать через логические операторы.

<xsl:when test="$colName='Бренд'">
<xsl:element name="brand"><xsl:value-of select="text:p"/></xsl:element><!-- например, выводим значение бренда -->
</xsl:when>

Но можно также работать и с подстроками, Например: есть столбцы называющиеся "Специальные характеристики" и "Подробные характеристики". Второе слово у них совпадает, плюс сами характеристики структурированные (при заполнении работал шаблон "Название характеристики": "Значение характеристики") - так что можно их обработать одним махом. Таким образом вместо перебора каждого условия,запишем в коде contains($colName, "характеристики") и под условие попадут оба варианта, но не попадёт вариант "Характеристики" из-за первой большой буквы. Для того, чтоб сработало условие и на него - либо оборачиваем $colName в функцию lower-case(). Получается конструкция contains(lower-case($colName), "характеристики").

Обработчики ячеек

Разобравшись с вопросом "Что может лежать в ячейке, на которой я сейчас нахожусь?", зададимся вопросом того "как это вывести в выходной файл?". Ниже я прилагаю примеры кода, используемые для вывода информации о товаре. Далее по тексту руководствуемся таким порядком: краткое название, пример(ы) кода и как оно работает. Так будет проще всего понять суть. Для копипаста - суть важно, что куски кода будут отображаться с рассчётом на то, что вставлять их надо будет внутрь блока <when> с условием выбора, методы сборки которых были рассмотрены выше.

Добавить атрибут тегу, внутри которого находимся

Шаблон:

<xsl:attribute name="ИМЯ АТРИБУТА"><xsl:value-of select="ЗНАЧЕНИЕ АТРИБУТА"/></xsl:attribute>

Пример:

<xsl:attribute name="id"><xsl:value-of select="text:p"/></xsl:attribute>

Тут всё просто. Тег xsl:attribute говорит обработчику, что надо в тег, внутри которого находится этот тег, добавить атрибут с именем "id" и передать ему тегущее значение ячейки.

Создать самостоятельный тег

Тут есть два варианта. Можно просто написать тег, как есть, а можно вызвать метод xsl:element и передать ему значение.

Шаблон:

  1. <name><xsl:value-of select="text:p"/></name>
  2. <xsl:element name="name"><xsl:value-of select="ЗНАЧЕНИЕ элемента"/></xsl:element>

Пример:

<name><xsl:value-of select="text:p"/></name>

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

ПОЛУЧИТЬ ПРЕДЛОЖЕНИЕ ОТ ДРОПШИППИНГ ПОСТАВЩИКА ИГРУШЕК "ПРЯМЫЕ ДИСТРИБЬЮЦИИ"

Войди, чтоб увидеть оптовые цены Войти