Обработка XML, XPath и XSL трансформации в Ruby
Изучая новую технологию всегда хочется применить её для решения текущих задач. А одна из основных задач современного программиста - это составление программ, которые собирают данные из нескольких систем, обрабатывают их и выдают результат. Это напоминает сборку модели из готовых деталей конструктора, где роль крупных блоков играют, например, базы данных, а в качестве соединительных деталей используется простой и гибкий язык программирования.
Основными источниками данных в современном программировании являются текстовые файлы, базы данных и файлы в XML формате. А обрабатывать и соединять их друг с другом попробуем с помощью скриптового языка программирования Ruby.
Обработка текстовых файлов не представляет особой сложности, поскольку возможности Ruby в области поддержки регулярных выражений делают разбор любого текстового файла не очень сложной задачей. А вот обработку XML документов можно рассмотреть подробнее.
Обработка XML
Для обработки XML существует как стандартное решение в виде rexml библиотеки, которая входит в Ruby 1.8, так и альтернативные варианты, которые в большинстве случаев представляют собой обертки (wrappers) вокруг С библиотек libxml2 и производных от неё.
Поиск расширений Ruby для обработки XML документов ( и на ) приводит к множеству библиотек. Но отбросив все alpha, unstable, experimental и тому подобное получаем совсем небольшой список:
* libgdome-ruby (beta):
* libxml (production quality):
* libxslt (working):
Я попробую сравнить найденные библиотеки между собой в решении простой задачи.
Постановка задачи
Программа 1. Генерация XML документа (generateXml.rb)
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)
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}"
Определение времени выполнения и результат
count(node): 1000, sum(sum): 1000, avg(avg): 499
real 0m6.035s
user 0m5.450s
sys 0m0.590s
Итого - 6 секунд длился разбор документа на моем компьютере.
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 () и glib (). Сам Gdome2 можно скачать с сайта
Далее переходим к установке Ruby расширения libgdome-ruby:
$ cd libgdome-ruby-0.3
$ ruby extconf.rb
$ make
$ make install
Программа 3. Решение задачи с использованием Gdome2 (parseXml_3.rb)
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:
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:
$ cd libxml-0.3.4
$ ruby extconf.rb
$ make && make install
Программа 4. Решение задачи с использованием libxml (parseXml_4.rb)
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}"
Традиционный замер времени выполнения:
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.
$ 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):
<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/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
Проверяем производительность:
... результат трансформации пропущен ...
real 0m0.064s
user 0m0.030s
sys 0m0.030s
Заключение
Резюмируя, можно сказать, что Ruby на данный момент обладает достаточными средствами для обработки XML документов и выполнения XSL трансформаций. Он соединяет лучшее, что было сделано в программировании - удобный синтаксис языка вместе с использованием существующих библиотек. Полученное в результате решение отличается простотой и легкостью в изучении, что делает его эффективным инструментом для программистов.

Обсуждение
Re: Обработка XML, XPath и XSL трансформации в Ruby
odds of winning at blackjack online
casino empire cheat
casino desktop wallpaper
poker travel kit
driving game
gamehouse poker
free atv game
tightpoker let it ride poker
casino fx royale trailer
probability of rolling a certain number on two dice
free monopoly game download
poker playing dogs painting
sands convention center las vegas
grand yavuz hotel
port 1025 blackjack
money making secret
loose slots vegas
make your own clay poker chips
lottosouth.+com
harrah's rincon casino
49 6 7 loto super
casino casino online poker slot yourbestonlinecasino.com
game of dГ©sire
how to make a roulette wheel
latex game free video
casinos gaming
casino fife
no deposit casino redeem coupon
niagara casino hotel
boonville capri casino isle mo
online blackjack game freed
pokerstars signup
game massive online rune scape
des francaise jeux loto
pokerstars problems
casino online rated top
bravo poker tv
lottery gambling
las vegas car for sale
high roller online casino
blotto
Read Amazed
Many of us know you are right, but unfortunately few of us will say it aloud. where to buy cialis