Каталог решений - Из html-таблиц в таблицы значений, функция

Из html-таблиц в таблицы значений, функция

Из html-таблиц в таблицы значений, функция

В наличии

Парсинг HTML-таблиц, занесение результатов в таблицы значений. Обработка вложенных друг в друга html-таблиц. Обработка объединённых ячеек. Одна функция — и готово.

Категория:

Описание

Делал тут чтение с одного сайта, да и написал функцию… Дай, думаю, выложу — авось прямо в таком виде кому пригодится. Что умеет: умеет из файла или из html-фрагмента читать все находящиеся в нём таблицы, включая вложенные друг в друга. Итоговый результат — массив из таблиц значений. В ячейки таблиц пишется либо простое значение (обычно строковое), либо вложенная таблица значений, либо массив значений (если ещё были узлы, в т.ч. вложенные таблицы). Колонки — произвольного типа, их именование примитивное, «к1», «к2» и т.д. На правильность чтения вертикально объединённых ячеек (rowSpan) не рассчитана.

Прошу пардону, но раскраска исходников лежит вне досягаемости; потом разрисую, а копипастить уже и так можно.

Функция ПолучитьТаблицыЗначенийИзHTML(рИсходныйДокумент,мТаблиц=Неопределено)

 Если мТаблиц=Неопределено Тогда // первый запуск, читаем сам документ

 мТаблицИтого=Новый Массив;

 рКодировка=«UTF-8»;

 чтен=Новый ЧтениеHTML;

 Если ТипЗнч(рИсходныйДокумент)=Тип(«Строка») Тогда

 // считаем, что передали строку HTML-кода (фрагмент)

 чтен.УстановитьСтроку(рИсходныйДокумент,рКодировка);

 ИначеЕсли ТипЗнч(рИсходныйДокумент)=Тип(«Файл») Тогда

 // считаем, что передали файл, проверенно существующий и читающийся оттуда, где он есть

 чтен.ОткрытьФайл(рИсходныйДокумент.ПолноеИмя,рКодировка);

 Иначе

 Сообщить(«Передан неверный аргумент: «+СокрЛП(рИсходныйДокумент)+«, недопустимый тип!»,СтатусСообщения.Важное);

 Возврат мТаблицИтого;

 КонецЕсли;

 пострДОМ=Новый ПостроительDOM;

 гдок=пострДОМ.Прочитать(чтен);

 // запускаем уже рекурсивное чтение

 ПолучитьТаблицыЗначенийИзHTML(гдок.ЭлементДокумента,мТаблицИтого);

 // возвращаемся с верхнего уровня и вообще выходим

 Возврат мТаблицИтого;

 Иначе

 // рекурсивный запуск, уже читается ДокументHTML

 Для каждого элдок Из рИсходныйДокумент.ДочерниеУзлы Цикл

 Если ТипЗнч(элдок)=Тип(«ЭлементТаблицаHTML») Тогда // таблица, переходим непосредственно к её обработке

 //===========================================================================================

 Если элдок.ДочерниеУзлы.Количество()=1 Тогда

 рЭлемент=элдок.ДочерниеУзлы.Элемент(0);

 Если ТипЗнч(рЭлемент)=Тип(«ЭлементHTML») Тогда

 Если рЭлемент.ЕстьДочерниеУзлы() Тогда

 // колонки добавляются по факту и по порядку

 тзнч=Новый ТаблицаЗначений;

 Для каждого рСтрока Из рЭлемент.ДочерниеУзлы Цикл

 ОбработкаПрерыванияПользователя();

 мЗначенийКолонок=Новый Массив;

 Для каждого рЯчейка Из рСтрока.ДочерниеУзлы Цикл

 ОбработкаПрерыванияПользователя();

 Если ТипЗнч(рЯчейка)<>Тип(«ЭлементЯчейкаТаблицыHTML») Тогда Продолжить КонецЕсли;

 // в ячейке может быть как один элемент (тогда вносится простое значение), так и несколько (тогда их массив)

 мЗначенийЯчейки=Новый Массив;

 Для каждого рУзел Из рЯчейка.ДочерниеУзлы ЦИкл

 Если ТипЗнч(рУзел)=Тип(«ТекстDOM») Тогда

 рЗначение=СокрЛП(рУзел.ТекстовоеСодержимое);

 ИначеЕсли ТипЗнч(рУзел)=Тип(«ЭлементТаблицаHTML») Тогда

 // идём ещё глубже, обрабатывая таблицу через вызов обработки её родителя

 мПодтаблиц=Новый Массив;

 ПолучитьТаблицыЗначенийИзHTML(рУзел.РодительскийУзел,мПодтаблиц);

 Если мПодтаблиц.Количество()=0 Тогда // ни одной таблицы не было

 рЗначение=Неопределено;

 ИначеЕсли мПодтаблиц.Количество()=1 Тогда

 рЗначение=мПодтаблиц.Получить(0);

 Иначе

 рЗначение=мПодтаблиц; // прямо как массив и идёт

 КонецЕсли;

 Иначе

 // идём ещё глубже в общем виде

 мПодтаблиц=Новый Массив;

 ПолучитьТаблицыЗначенийИзHTML(рУзел,мПодтаблиц);

 Если мПодтаблиц.Количество()=0 Тогда // ни одной таблицы не было

 рЗначение=Неопределено;

 ИначеЕсли мПодтаблиц.Количество()=1 Тогда

 рЗначение=мПодтаблиц.Получить(0);

 Иначе

 рЗначение=мПодтаблиц; // прямо как массив и идёт

 КонецЕсли;

 КонецЕсли;

 Если ТипЗнч(рЗначение)=Тип(«Массив») Тогда // перекидываем в итоговый

 Для каждого знчм Из рЗначение Цикл мЗначенийЯчейки.Добавить(знчм) КонецЦикла;

 Иначе // просто добавляем

 мЗначенийЯчейки.Добавить(рЗначение);

 КонецЕсли;

 КонецЦикла;

 рЗначениеЯчейки=?(мЗначенийЯчейки.Количество()=1,мЗначенийЯчейки[0],мЗначенийЯчейки);

 // определяем, сколько колонок вмещает текущая ячейка (возможно объединение, тогда будет повтор значения)

 квокол=?(рЯчейка.ОбъединениеКолонок=0,1,рЯчейка.ОбъединениеКолонок);

 //Если рЯчейка.Атрибуты.Количество()<>0 Тогда // можно и так, оставил для общего интересу…

 // рАтрОбъКол=рЯчейка.Атрибуты.ПолучитьИменованныйЭлемент(«colspan»); // именно в нижнем регистре

 // Если рАтрОбъКол<>Неопределено Тогда квокол=рАтрОбъКол.Значение КонецЕсли;

 //КонецЕсли;

 Для й=1 По квокол Цикл

 мЗначенийКолонок.Добавить(рЗначениеЯчейки);

 КонецЦикла;

 КонецЦикла;

 // теперь массив значений для строки таблицы значений готов

 стротзнч=тзнч.Добавить();

 Для ы=0 По мЗначенийКолонок.Количество()-1 Цикл

 Если ы>тзнч.Колонки.Количество()-1 Тогда // по ситуации добавляем колонку произвольного типа

 тзнч.Колонки.Добавить(«к»+СокрЛП(ы));

 КонецЕсли;

 стротзнч[ы]=мЗначенийКолонок.Получить(ы);

 КонецЦикла;

 КонецЦикла;

 Иначе

 тзнч=Неопределено;

 КонецЕсли; // если есть дочерние/нет дочерних

 Иначе

 тзнч=Неопределено;

 КонецЕсли; // по типу исходного основного элемента таблицы

 Иначе

 тзнч=Неопределено;

 КонецЕсли; // по количеству исходных узлов

 //===========================================================================================

 Если тзнч<>Неопределено Тогда мТаблиц.Добавить(тзнч) КонецЕсли;

 Иначе

 Если элдок.ЕстьДочерниеУзлы() Тогда

 ПолучитьТаблицыЗначенийИзHTML(элдок,мТаблиц);

 КонецЕсли;

 КонецЕсли;

 КонецЦикла;

 КонецЕсли;

 Возврат Неопределено; // тут результат нас не интересует

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

 

has been added to your cart:
Оформление заказа