Делал тут чтение с одного сайта, да и написал функцию… Дай, думаю, выложу — авось прямо в таком виде кому пригодится. Что умеет: умеет из файла или из 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(элдок,мТаблиц);
КонецЕсли;
КонецЕсли;
КонецЦикла;
КонецЕсли;
Возврат Неопределено; // тут результат нас не интересует
КонецФункции
(0) оформите пожалуйста код, как полагается.
(1) Я ж написал, разукрашки под рукой не случилось. 😉 Сегодня оформлю.
А есть возможность обратной реализации?
Из Таблицы значений (со вложенными таблицами) в таблицу HTML ?
Пригодилось бы.
(3) Уж подумываю сделать, есть такая задача.
Отлично.
Яростно плюсую за то, что описал в статье примеры кода.
(5) Сделал:http://infostart.ru/public/174149/
у меня не отрабатывает: в моем файле таблица имеет более 1 строки, а у Вас стоит
Если элдок.ДочерниеУзлы.Количество()=1 Тогда
накосячил с копипастом )))
(8) Фух, я уж напрягся. Если что, пишите.
Если таблица с заголовком
, то не обрабатывает такие таблицы корректно, а ячейки такого заголовка имеют тип как ЭлементHTML
не работает. в документе у меня одна таблица. возвращает массив с кучей пустых строк…. 🙁
(11) Пожалуйста, киньте мне на yashazz пёсик mail.ру ваш исходный html, посмотрю. Очень интересно, что там такое попалось.
Заранее спасибо =). Завтра буду юзать
У меня то же самое что и 11
(14) andy3626603, жду ваш html, посмотрим.
Не отрабаытвает если ДочерниеУзлы.Количество() > 1
Если элдок.ДочерниеУзлы.Количество()=1 Тогда
рЭлемент=элдок.ДочерниеУзлы.Элемент(0);