Ruby - Tutorial de XML, XSLT y XPath
¿Qué es XML?
El Lenguaje de marcado extensible (XML) es un lenguaje de marcado muy parecido a HTML o SGML. Esto es recomendado por el World Wide Web Consortium y está disponible como estándar abierto.
XML es un lenguaje portátil de código abierto que permite a los programadores desarrollar aplicaciones que pueden ser leídas por otras aplicaciones, independientemente del sistema operativo y / o lenguaje de desarrollo.
XML es extremadamente útil para realizar un seguimiento de pequeñas o medianas cantidades de datos sin necesidad de una red troncal basada en SQL.
Arquitecturas y API de XML Parser
Hay dos sabores diferentes disponibles para analizadores XML:
SAX-like (Stream interfaces)- Aquí registra devoluciones de llamada para eventos de interés y luego deja que el analizador continúe con el documento. Esto es útil cuando sus documentos son grandes o tiene limitaciones de memoria, analiza el archivo a medida que lo lee desde el disco y el archivo completo nunca se almacena en la memoria.
DOM-like (Object tree interfaces) - Esta es la recomendación del World Wide Web Consortium en la que todo el archivo se lee en la memoria y se almacena en forma jerárquica (basada en árboles) para representar todas las características de un documento XML.
SAX obviamente no puede procesar información tan rápido como DOM cuando trabaja con archivos grandes. Por otro lado, usar DOM exclusivamente puede matar realmente sus recursos, especialmente si se usa en muchos archivos pequeños.
SAX es de solo lectura, mientras que DOM permite cambios en el archivo XML. Dado que estas dos API diferentes se complementan literalmente entre sí, no hay ninguna razón por la que no pueda usarlas para proyectos grandes.
Analizando y creando XML usando Ruby
La forma más común de manipular XML es con la biblioteca REXML de Sean Russell. Desde 2002, REXML ha sido parte de la distribución estándar de Ruby.
REXML es un procesador XML puro de Ruby que cumple con el estándar XML 1.0. Es un procesador sin validación , que pasa todas las pruebas de conformidad sin validación de OASIS.
El analizador REXML tiene las siguientes ventajas sobre otros analizadores disponibles:
- Está escrito al 100 por ciento en Ruby.
- Se puede utilizar para el análisis de SAX y DOM.
- Es ligero, menos de 2000 líneas de código.
- Los métodos y las clases son realmente fáciles de entender.
- API basada en SAX2 y soporte completo de XPath.
- Se envía con la instalación de Ruby y no se requiere instalación por separado.
Para todos nuestros ejemplos de código XML, usemos un archivo XML simple 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álisis similar al DOM
Primero analicemos nuestros datos XML en forma de árbol . Comenzamos por exigir elrexml/documentbiblioteca; a menudo hacemos un REXML incluido para importarlo al espacio de nombres de nivel superior por conveniencia.
#!/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
}
Esto producirá el siguiente 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álisis tipo SAX
Para procesar los mismos datos, películas.xml , archivo de una manera orientada a la transmisión , definiremos una clase de escucha cuyos métodos serán el objetivo de las devoluciones de llamada del analizador.
NOTE - No se sugiere usar un análisis similar a SAX para un archivo pequeño, esto es solo para un ejemplo de demostración.
#!/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)
Esto producirá el siguiente 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 y Ruby
Una forma alternativa de ver XML es XPath. Este es un tipo de pseudolenguaje que describe cómo ubicar elementos y atributos específicos en un documento XML, tratando ese documento como un árbol lógico ordenado.
REXML tiene soporte XPath a través de la clase XPath . Asume un análisis basado en árboles (modelo de objeto de documento) como hemos visto anteriormente.
#!/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
Esto producirá el siguiente resultado:
<movie title = 'Enemy Behind'> ... </>
War, Thriller
Anime, Science Fiction
Anime, Action
Comedy
["DVD", "DVD", "DVD", "VHS"]
XSLT y Ruby
Hay dos analizadores XSLT disponibles que Ruby puede usar. Aquí se ofrece una breve descripción de cada uno.
Ruby-Sablotron
Este analizador está escrito y mantenido por Masayoshi Takahashi. Esto está escrito principalmente para el sistema operativo Linux y requiere las siguientes bibliotecas:
- Sablot
- Iconv
- Expat
Puede encontrar este módulo en Ruby-Sablotron.
XSLT4R
XSLT4R está escrito por Michael Neumann y se puede encontrar en el RAA en la sección Biblioteca en XML. XSLT4R usa una interfaz de línea de comandos simple, aunque también se puede usar dentro de una aplicación de terceros para transformar un documento XML.
XSLT4R necesita XMLScan para funcionar, que se incluye dentro del archivo XSLT4R y que también es un módulo 100% Ruby. Estos módulos se pueden instalar utilizando el método de instalación estándar de Ruby (es decir, ruby install.rb).
XSLT4R tiene la siguiente sintaxis:
ruby xslt.rb stylesheet.xsl document.xml [arguments]
Si desea utilizar XSLT4R desde una aplicación, puede incluir XSLT e ingresar los parámetros que necesite. Aquí está el ejemplo:
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 )
Otras lecturas
Para obtener detalles completos sobre el analizador REXML, consulte la documentación estándar para la documentación del analizador REXML .
Puede descargar XSLT4R desde RAA Repository .