Ruby - Tutorial de XML, XSLT e XPath
O que é XML?
A Extensible Markup Language (XML) é uma linguagem de marcação muito parecida com HTML ou SGML. Isso é recomendado pelo World Wide Web Consortium e está disponível como um padrão aberto.
XML é uma linguagem portátil e de código aberto que permite aos programadores desenvolver aplicativos que podem ser lidos por outros aplicativos, independentemente do sistema operacional e / ou linguagem de desenvolvimento.
XML é extremamente útil para rastrear pequenas e médias quantidades de dados sem exigir um backbone baseado em SQL.
Arquiteturas XML Parser e APIs
Existem dois sabores diferentes disponíveis para analisadores XML -
SAX-like (Stream interfaces)- Aqui você registra retornos de chamada para eventos de interesse e, em seguida, permite que o analisador prossiga pelo documento. Isso é útil quando seus documentos são grandes ou você tem limitações de memória, ele analisa o arquivo à medida que o lê do disco e o arquivo inteiro nunca é armazenado na memória.
DOM-like (Object tree interfaces) - Esta é a recomendação do World Wide Web Consortium em que todo o arquivo é lido na memória e armazenado em uma forma hierárquica (baseada em árvore) para representar todos os recursos de um documento XML.
Obviamente, o SAX não pode processar informações tão rápido quanto o DOM ao trabalhar com arquivos grandes. Por outro lado, usar o DOM exclusivamente pode realmente matar seus recursos, especialmente se usado em muitos arquivos pequenos.
SAX é somente leitura, enquanto DOM permite alterações no arquivo XML. Uma vez que essas duas APIs diferentes se complementam literalmente, não há razão para que você não possa usá-las para grandes projetos.
Análise e criação de XML usando Ruby
A maneira mais comum de manipular XML é com a biblioteca REXML de Sean Russell. Desde 2002, REXML faz parte da distribuição padrão do Ruby.
REXML é um processador XML Ruby puro em conformidade com o padrão XML 1.0. É um processador de não validação , passando em todos os testes de conformidade de não validação OASIS.
O analisador REXML tem as seguintes vantagens sobre outros analisadores disponíveis -
- Está escrito 100 por cento em Ruby.
- Ele pode ser usado para análise SAX e DOM.
- É leve, com menos de 2.000 linhas de código.
- Métodos e classes são realmente fáceis de entender.
- API baseada em SAX2 e suporte completo a XPath.
- Enviado com a instalação do Ruby e nenhuma instalação separada é necessária.
Para todos os nossos exemplos de código XML, vamos usar um arquivo XML simples como entrada -
<collection shelf = "New Arrivals">
<movie title = "Enemy Behind">
<type>War, Thriller</type>
<format>DVD</format>
<year>2003</year>
<rating>PG</rating>
<stars>10</stars>
<description>Talk about a US-Japan war</description>
</movie>
<movie title = "Transformers">
<type>Anime, Science Fiction</type>
<format>DVD</format>
<year>1989</year>
<rating>R</rating>
<stars>8</stars>
<description>A schientific fiction</description>
</movie>
<movie title = "Trigun">
<type>Anime, Action</type>
<format>DVD</format>
<episodes>4</episodes>
<rating>PG</rating>
<stars>10</stars>
<description>Vash the Stampede!</description>
</movie>
<movie title = "Ishtar">
<type>Comedy</type>
<format>VHS</format>
<rating>PG</rating>
<stars>2</stars>
<description>Viewable boredom</description>
</movie>
</collection>
Análise semelhante a DOM
Vamos primeiro analisar nossos dados XML em forma de árvore . Começamos exigindo orexml/documentbiblioteca; frequentemente, incluímos REXML para importar para o namespace de nível superior por conveniência.
#!/usr/bin/ruby -w
require 'rexml/document'
include REXML
xmlfile = File.new("movies.xml")
xmldoc = Document.new(xmlfile)
# Now get the root element
root = xmldoc.root
puts "Root element : " + root.attributes["shelf"]
# This will output all the movie titles.
xmldoc.elements.each("collection/movie"){
|e| puts "Movie Title : " + e.attributes["title"]
}
# This will output all the movie types.
xmldoc.elements.each("collection/movie/type") {
|e| puts "Movie Type : " + e.text
}
# This will output all the movie description.
xmldoc.elements.each("collection/movie/description") {
|e| puts "Movie Description : " + e.text
}
Isso produzirá o seguinte resultado -
Root element : New Arrivals
Movie Title : Enemy Behind
Movie Title : Transformers
Movie Title : Trigun
Movie Title : Ishtar
Movie Type : War, Thriller
Movie Type : Anime, Science Fiction
Movie Type : Anime, Action
Movie Type : Comedy
Movie Description : Talk about a US-Japan war
Movie Description : A schientific fiction
Movie Description : Vash the Stampede!
Movie Description : Viewable boredom
Análise semelhante a SAX
Para processar os mesmos dados, movies.xml , arquivo de uma maneira orientada a fluxo , definiremos uma classe de ouvinte cujos métodos serão o alvo de callbacks do analisador.
NOTE - Não é sugerido usar análise semelhante a SAX para um arquivo pequeno, isso é apenas para um exemplo de demonstração.
#!/usr/bin/ruby -w
require 'rexml/document'
require 'rexml/streamlistener'
include REXML
class MyListener
include REXML::StreamListener
def tag_start(*args)
puts "tag_start: #{args.map {|x| x.inspect}.join(', ')}"
end
def text(data)
return if data =~ /^\w*$/ # whitespace only
abbrev = data[0..40] + (data.length > 40 ? "..." : "")
puts " text : #{abbrev.inspect}"
end
end
list = MyListener.new
xmlfile = File.new("movies.xml")
Document.parse_stream(xmlfile, list)
Isso produzirá o seguinte resultado -
tag_start: "collection", {"shelf"=>"New Arrivals"}
tag_start: "movie", {"title"=>"Enemy Behind"}
tag_start: "type", {}
text : "War, Thriller"
tag_start: "format", {}
tag_start: "year", {}
tag_start: "rating", {}
tag_start: "stars", {}
tag_start: "description", {}
text : "Talk about a US-Japan war"
tag_start: "movie", {"title"=>"Transformers"}
tag_start: "type", {}
text : "Anime, Science Fiction"
tag_start: "format", {}
tag_start: "year", {}
tag_start: "rating", {}
tag_start: "stars", {}
tag_start: "description", {}
text : "A schientific fiction"
tag_start: "movie", {"title"=>"Trigun"}
tag_start: "type", {}
text : "Anime, Action"
tag_start: "format", {}
tag_start: "episodes", {}
tag_start: "rating", {}
tag_start: "stars", {}
tag_start: "description", {}
text : "Vash the Stampede!"
tag_start: "movie", {"title"=>"Ishtar"}
tag_start: "type", {}
tag_start: "format", {}
tag_start: "rating", {}
tag_start: "stars", {}
tag_start: "description", {}
text : "Viewable boredom"
XPath e Ruby
Uma forma alternativa de visualizar XML é XPath. Este é um tipo de pseudo-linguagem que descreve como localizar elementos e atributos específicos em um documento XML, tratando esse documento como uma árvore ordenada lógica.
REXML tem suporte XPath por meio da classe XPath . Ele assume a análise baseada em árvore (modelo de objeto de documento) como vimos acima.
#!/usr/bin/ruby -w
require 'rexml/document'
include REXML
xmlfile = File.new("movies.xml")
xmldoc = Document.new(xmlfile)
# Info for the first movie found
movie = XPath.first(xmldoc, "//movie")
p movie
# Print out all the movie types
XPath.each(xmldoc, "//type") { |e| puts e.text }
# Get an array of all of the movie formats.
names = XPath.match(xmldoc, "//format").map {|x| x.text }
p names
Isso produzirá o seguinte resultado -
<movie title = 'Enemy Behind'> ... </>
War, Thriller
Anime, Science Fiction
Anime, Action
Comedy
["DVD", "DVD", "DVD", "VHS"]
XSLT e Ruby
Existem dois analisadores XSLT disponíveis que Ruby pode usar. Uma breve descrição de cada um é fornecida aqui.
Ruby-Sablotron
Este analisador foi escrito e mantido por Masayoshi Takahashi. Isso foi escrito principalmente para o sistema operacional Linux e requer as seguintes bibliotecas -
- Sablot
- Iconv
- Expat
Você pode encontrar este módulo em Ruby-Sablotron.
XSLT4R
XSLT4R foi escrito por Michael Neumann e pode ser encontrado no RAA na seção Biblioteca em XML. O XSLT4R usa uma interface de linha de comando simples, embora possa, alternativamente, ser usado em um aplicativo de terceiros para transformar um documento XML.
O XSLT4R precisa do XMLScan para operar, que está incluído no arquivo XSLT4R e que também é um módulo Ruby 100 por cento. Esses módulos podem ser instalados usando o método de instalação padrão do Ruby (ou seja, ruby install.rb).
XSLT4R tem a seguinte sintaxe -
ruby xslt.rb stylesheet.xsl document.xml [arguments]
Se quiser usar o XSLT4R de dentro de um aplicativo, você pode incluir o XSLT e inserir os parâmetros necessários. Aqui está o exemplo -
require "xslt"
stylesheet = File.readlines("stylesheet.xsl").to_s
xml_doc = File.readlines("document.xml").to_s
arguments = { 'image_dir' => '/....' }
sheet = XSLT::Stylesheet.new( stylesheet, arguments )
# output to StdOut
sheet.apply( xml_doc )
# output to 'str'
str = ""
sheet.output = [ str ]
sheet.apply( xml_doc )
Leitura Adicional
Para obter detalhes completos sobre o REXML Parser, consulte a documentação padrão para REXML Parser Documentation .
Você pode baixar o XSLT4R no repositório RAA .