The OpenNET Project / Index page

[ новости /+++ | форум | теги | ]

Оптимальная обработка XML+XSL на Ruby (xml ruby benchmark)


<< Предыдущая ИНДЕКС Поиск в статьях src Установить закладку Перейти на закладку Следующая >>
Ключевые слова: xml, ruby, benchmark,  (найти похожие документы)
From: Александр Неткачев <http://devlink.crimea.ua>; Date: Mon, 20 Sep 2004 18:21:07 +0000 (UTC) Subject: Оптимальная обработка XML+XSL на Ruby Оригинал: http://devlink.crimea.ua/articles/article.php?article_id=21 Обработка XML+XSL на Ruby Александр Неткачев 19.05.2004 - Введение - Обработка XML - Постановка задачи - Решение задачи методами rexml - Решение задачи c помощью libgdome-ruby - Победитель - Оболочка для libxml - Вкусность на последок: XSL трансформация с использованием libxslt. - Заключение Введение Изучая новую технологию всегда хочется применить её для решения текущих задач. А одна из основных задач современного программиста - это составление программ, которые собирают данные из нескольких систем, обрабатывают их и выдают результат. Это напоминает сборку модели из готовых деталей конструктора, где роль крупных блоков играют, например, базы данных, а в качестве соединительных деталей используется простой и гибкий язык программирования. Основными источниками данных в современном программировании являются текстовые файлы, базы данных и файлы в XML формате. А обрабатывать и соединять их друг с другом попробуем с помощью скриптового языка программирования Ruby. Обработка текстовых файлов не представляет особой сложности, поскольку возможности Ruby в области поддержки регулярных выражений делают разбор любого текстового файла не очень сложной задачей. А вот обработку XML документов можно рассмотреть подробнее. Обработка XML Для обработки XML существует как стандартное решение в виде rexml библиотеки, которая входит в Ruby 1.8, так и альтернативные варианты, которые в большинстве случаев представляют собой обертки (wrappers) вокруг С библиотек libxml2 и производных от неё. Поиск расширений Ruby для обработки XML документов (http://raa.ruby-lang.org/search.rhtml?search=xml и на http://libxml.org) приводит к множеству библиотек. Но отбросив все alpha, unstable, experimental и тому подобное получаем совсем небольшой список: * libgdome-ruby (beta): http://raa.ruby-lang.org/project/libgdome-ruby/ * libxml (production quality): http://raa.ruby-lang.org/project/libxml/ * libxslt (working): [18]http://raa.ruby-lang.org/project/libxslt/ Я попробую сравнить найденные библиотеки между собой в решении простой задачи. Постановка задачи Программа 1. Генерация XML документа (generateXml.rb) puts '<nodes>' 1000.times {|i| puts '<node sum="1" avg="' + i.to_s + '">Node sample text</node>'} puts '</nodes>' Задача В сгенерированном программой 1 XML документе пройтись по всем узлам, посчитать сумму атрибутов sum и найти среднее значение атрибута avg. Решение задачи методами rexml Удобный API компенсируется недостатком производительности. Дело в том, что библиотека rexml написана на самом Ruby, производительность которого относительно C/C++ не велика. Также можно отметить, что XSL трансформацию библиотека rexml не поддерживает. Программа 2. Решение задачи (parseXml_2.rb) require "rexml/document" include REXML xmlStr = '' ARGF.each {|line| xmlStr << line} doc = Document.new xmlStr sum = avgSum = count = 0 doc.elements.each('/nodes/node') { |e| count += 1 sum += e.attributes['sum'].to_i avgSum += e.attributes['avg'].to_i } puts "count(node): #{count}, sum(sum): #{sum}, avg(avg): #{avgSum/count}" Определение времени выполнения и результат $ time ruby generateXml.rb | ruby parseXml_2.rb count(node): 1000, sum(sum): 1000, avg(avg): 499 real 0m6.035s user 0m5.450s sys 0m0.590s Итого - 6 секунд длился разбор документа на моем компьютере. model name : Celeron (Mendocino) cpu MHz : 534.552 cache size : 128 KB bogomips : 1064.96 Решение задачи c помощью libgdome-ruby libgdome-ruby-0.3.tar.bz2 представляет собой оболочку вокруг Gdome2 библиотеки. Gdome2 - это реализация W3C DOM Level2 на C. Поэтому для установки libgdome-ruby надо сначала установить Gdome2 библиотеку. Тут и пригодится Portage от Gentoo Linux: $ emerge dev-libs/gdome2 Для ручной установки замечу, что Gdome2 зависит от библиотек libxml2 (http://xmlsoft.org/) и glib (http://www.gtk.org/). Сам Gdome2 можно скачать с сайта http://phd.cs.unibo.it/gdome2/ Далее переходим к установке Ruby расширения libgdome-ruby: $ tar -xjf libgdome-ruby-0.3.tar.bz2 $ cd libgdome-ruby-0.3 $ ruby extconf.rb $ make $ make install Программа 3. Решение задачи с использованием Gdome2 (parseXml_3.rb) require "gdome" xmlStr = '' ARGF.each {|line| xmlStr << line} domImpl = Dom::implementation doc = domImpl.createDocFromMemory(xmlStr, 0) sum = avgSum = count = 0 children = doc.documentElement.childNodes (0...children.length).each{ |i| el = children.item(i) if (el.kind_of?(Dom::Element)) count += 1 sum += el.getAttribute('sum').to_i avgSum += el.getAttribute('avg').to_i end } puts "count(node): #{count}, sum(sum): #{sum}, avg(avg): #{avgSum/count}" Можно задать резонный вопрос: почему я не использовал XPath, для выборки узлов /Nodes/Node. Отвечаю - в библиотеке libgdome-ruby XPath не реализовали, хотя в самой Gnome2 XPath присутствует в полной мере. Отметим, что XSL трансформация не реализована в Gdom2 и, как следствие, в libgdome-ruby тоже. Время выполнения задачи с использованием gdome значительно лучше, чем с rexml: $ time ruby generateXml.rb | ruby parseXml_3.rb count(node): 1000, sum(sum): 1000, avg(avg): 499 real 0m0.334s user 0m0.300s sys 0m0.030s Победитель - Оболочка для libxml Заявленая автором оболочки поддержка XPath и простые и напоминающие rexml интерфейсы весьма привлекательны. Библиотека зависит от libm (математические функции), libz (zlib), libiconv и, естественно, от libxml2. Как правило, все эти библиотеки в современных дистрибутивах есть, поэтому переходим без лишних слов к установке и реализации нашей задачи: Устанавливаем скачаный файл libxml-0.3.4.tar.gz: $ tar -xzf libxml-0.3.4.tar.gz $ cd libxml-0.3.4 $ ruby extconf.rb $ make && make install Программа 4. Решение задачи с использованием libxml (parseXml_4.rb) require 'xml/libxml' xmlStr = '' ARGF.each {|line| xmlStr << line} xp = XML::Parser.new() xp.string = xmlStr doc = xp.parse sum = avgSum = count = 0 doc.find('/nodes/node').each { |e| count += 1 sum += e['sum'].to_i avgSum += e['avg'].to_i } puts "count(node): #{count}, sum(sum): #{sum}, avg(avg): #{avgSum/count}" Традиционный замер времени выполнения: $ time ruby generateXml.rb | ruby parseXml_4.rb count(node): 1000, sum(sum): 1000, avg(avg): 499 real 0m0.210s user 0m0.180s sys 0m0.030s Можно сказать только одно: Кубок победителю :-) Ruby libxml extention показал лучший результат по эффективности и удобству интерфейсов. Вкусность на последок: XSL трансформация с использованием libxslt. Для установки libxslt требуется, что бы libxml уже было установлено и header файлы находились в директории ../libxml относительно директории с libxslt. $ ln -s libxml-0.3.4 libxml $ tar -xzf libxslt-0.3.4.tar.gz $ cd libxslt-0.3.4 $ ruby extconf.rb $ make && make install Для примера предположим, что нам надо вывести список файлов в директории. Довольно простая задача, но при этом требуется разделить данные от представления. Это может понадобится, например, если дизайн представления будет менятся. Примерная реализация: получаем список файлов в директории, строим из списка файлов XML и трансформируем его в HTML при помощи XSL. XSL файл для трансформации (filesToHtml.xsl): <?xml version="1.0" ?> <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> <xsl:template match="/"> <html><body><ul> <xsl:for-each select="/files/file"> <li><xsl:value-of select="."/></li> </xsl:for-each> </ul></body></html> </xsl:template> </xsl:stylesheet> Ruby скрипт, осуществляющий трансформацию (buildFileList.rb): require 'xml/libxml' require 'xml/libxslt' xslt = XML::XSLT.file('filesToHtml.xsl') xp = XML::Parser.new # замечатальный пример компакности Ruby - выполнение shell комманды, # проход по строкам её результата и составление XML в одной строке :-) xp.string = `ls`.inject('<files>') { |xml, file| xml << '<file>' << file.chomp << '</file>' } + '</files>' xslt.doc = xp.parse s = xslt.parse s.apply s.print Проверяем производительность: $ time ruby buildFileList.rb ... результат трансформации пропущен ... real 0m0.064s user 0m0.030s sys 0m0.030s Заключение Резюмируя, можно сказать, что Ruby на данный момент обладает достаточными средствами для обработки XML документов и выполнения XSL трансформаций. Он соединяет лучшее, что было сделано в программировании - удобный синтаксис языка вместе с использованием существующих библиотек. Полученное в результате решение отличается простотой и легкостью в изучении, что делает его эффективным инструментом для программистов.

<< Предыдущая ИНДЕКС Поиск в статьях src Установить закладку Перейти на закладку Следующая >>

Обсуждение [ RSS ]
  • 1, leonardinius (ok), 10:37, 15/06/2006 [ответить]  
  • +/
    круто. я смотрю ты серьзно решил затестить связку руби/хмл. а как насчет сравнения с джабой? я думаю было бы интересно. насколько мне известно, она тормозит на обработке хмл документво.
    если не трудно и не лень .) - не мог бы и это продемонстрировать
     
  • 2, Виталий (??), 08:27, 04/10/2007 [ответить]  
  • +/
    Хорошая статья, любуюсь на нее уже не первый год, действительно хорошая, побольше бы таких обзоров.

    Предлагаю развить тему включив описание работы с XML из JRuby через использование стандартных классов Java из Ruby, вроде того как это сделанно здесь

    , в самом Ruby с этим вопросом ничего не изменилось с тех пор как вы делали данную статью.

     

     Добавить комментарий
    Имя:
    E-Mail:
    Заголовок:
    Текст:




    Партнёры:
    PostgresPro
    Inferno Solutions
    Hosting by Hoster.ru
    Хостинг:

    Закладки на сайте
    Проследить за страницей
    Created 1996-2024 by Maxim Chirkov
    Добавить, Поддержать, Вебмастеру