Продолжаю экспериментировать с Ruby и Tcl. И я решил написать на каждом из этих языков парсер xhtml-документов. Задача - преобразовать все xhtml-документы в текущей директории в текстовые документы. Преобразование самое простое - в сущности оно заключается просто в удалении тэгов из документа. На обоих языках задача была выполнена.
Програма на Tcl выглядит следующим образом
package require xml
set skip_data false
set result ""
#колбэк для обработки текста xml-элемента
proc cdata {data args} {
global skip_data
global result
if {$skip_data == false } {
append result $data
}
set skip_data false
}
#колбэк для обработки начала xml-элемента.
#если встречаются тэги <style> или <title>, то мы их пропускаем
proc elem {data attlist args} {
global skip_data
if {$data == "style"} {
set skip_data true
} elseif {$data == "title"} {
set skip_data true
}
}
set l [eval glob *.html]
set b [split $l]
# b - список html-файлов в текущей директории
foreach fn $b {
#считываем содержимое файла
set f [eval open $fn]
set data [eval read $f]
close $f
#создаём парсер и указываем колбэки
set parser [::xml::parser -characterdatacommand cdata -elementstartcommand elem]
$parser parse $data
set result [string trim $result]
set ofn $fn
append ofn {.txt}
#записываем результат в файл
set res_file [open $ofn w]
puts $res_file $result
close $res_file
}
На Ruby получился следующий код
require 'rexml/parsers/PullParser'
$result = ""
#получаем список html-фалов
h_files = Dir.glob("*.html")
#обрабатываем в цикле все эти файлы
for fn in h_files
#считываем данные
f = File.open(fn, "r")
if(f.eof)
p "empty"
return
end
res = f.read
#создаём парсер
lp = REXML::Parsers::PullParser.new(res)
skip_element = 0
while(lp.has_next?)
data = lp.pull
if(skip_element > 0)
skip_element -= 1
next
end
#если попадается ненужный элемент, то пропускаем его
if(data.start_element? && (data[0] == "style" data[0] == "title"))
skip_element = 2
end
if(data.text?)
#а если нужный, то сохраняем его
$result = $result + data[0].to_s
end
end
#записываем результат в файл
res = File.open(fn.to_s + ".txt", "w")
res.write($result.strip)
end
Несмотря на то, что текст програмы на Ruby получился лаконичнее, чем на Tcl, на Ruby вариант у меня ушло значительно больше времени, большую часть из которого я потратил на то, чтобы найти и использовать подходящий xml-парсер. Кроме того результат, который выдаёт Ruby, некорректен - в тексте сохранились значки " ". Хотя конечно это недостаток парсера, а не языка... Тем не менее Tcl в данном случае показал себя гораздо лучше. Правда при этом програма на Ruby работает примерно в два раза быстрее.
Комментариев нет:
Отправить комментарий