Ruby - XML, XSLT ve XPath Eğitimi

XML nedir?

Genişletilebilir Biçimlendirme Dili (XML), HTML veya SGML'ye çok benzer bir biçimlendirme dilidir. Bu, World Wide Web Consortium tarafından önerilir ve açık bir standart olarak mevcuttur.

XML, programcıların işletim sistemi ve / veya geliştirme dili ne olursa olsun diğer uygulamalar tarafından okunabilen uygulamalar geliştirmesine olanak tanıyan taşınabilir, açık kaynaklı bir dildir.

XML, SQL tabanlı bir omurga gerektirmeden küçük ila orta büyüklükteki verileri izlemek için son derece kullanışlıdır.

XML Ayrıştırıcı Mimarileri ve API'leri

XML ayrıştırıcılar için kullanılabilen iki farklı çeşit vardır -

  • SAX-like (Stream interfaces)- Burada, ilgili olaylar için geri aramaları kaydedersiniz ve ardından ayrıştırıcının belge boyunca ilerlemesine izin verirsiniz. Bu, belgeleriniz büyük olduğunda veya bellek sınırlamalarınız olduğunda kullanışlıdır, dosyayı diskten okurken ayrıştırır ve dosyanın tamamı hiçbir zaman bellekte depolanmaz.

  • DOM-like (Object tree interfaces) - Bu, tüm dosyanın belleğe okunduğu ve bir XML belgesinin tüm özelliklerini temsil etmek için hiyerarşik (ağaç tabanlı) bir biçimde depolandığı World Wide Web Consortium önerisidir.

SAX, büyük dosyalarla çalışırken DOM'un yapabildiği kadar hızlı bilgiyi işleyemez. Öte yandan, yalnızca DOM'u kullanmak, özellikle çok sayıda küçük dosyada kullanılıyorsa, kaynaklarınızı gerçekten öldürebilir.

SAX salt okunurdur, DOM ise XML dosyasında değişikliklere izin verir. Bu iki farklı API, kelimenin tam anlamıyla birbirini tamamladığından, her ikisini de büyük projelerde kullanamamanız için hiçbir neden yoktur.

Ruby Kullanarak XML Ayrıştırma ve Oluşturma

XML'i işlemenin en yaygın yolu Sean Russell'ın REXML kitaplığıdır. REXML 2002'den beri standart Ruby dağıtımının bir parçası olmuştur.

REXML, XML 1.0 standardına uygun saf bir Ruby XML işlemcisidir. Bu ise olmayan doğrulama OASIS olmayan doğrulama uyumluluk testleri her geçen işlemci.

REXML ayrıştırıcısı, diğer mevcut ayrıştırıcılara göre şu avantajlara sahiptir:

  • Ruby'de yüzde 100 yazılmıştır.
  • Hem SAX hem de DOM ayrıştırma için kullanılabilir.
  • Hafiftir, 2000 satırdan az koddur.
  • Yöntemler ve sınıflar gerçekten anlaşılması kolaydır.
  • SAX2 tabanlı API ve Tam XPath desteği.
  • Ruby kurulumuyla gönderilir ve ayrı bir kurulum gerekmez.

Tüm XML kodu örneklerimiz için, girdi olarak basit bir XML dosyası kullanalım -

<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>

DOM benzeri Ayrıştırma

Öncelikle XML verilerimizi ağaç tarzında ayrıştıralım . İsteyerek başlıyoruzrexml/documentkütüphane; genellikle kolaylık sağlamak için üst düzey ad alanına içe aktarmak için bir REXML dahil ederiz.

#!/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 
}

Bu, aşağıdaki sonucu verecektir -

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

SAX benzeri Ayrıştırma

Aynı verileri, movies.xml dosyasını, akış odaklı bir şekilde işlemek için , yöntemleri ayrıştırıcıdan gelen geri aramaların hedefi olacak bir dinleyici sınıfı tanımlayacağız .

NOTE - Küçük bir dosya için SAX benzeri ayrıştırmanın kullanılması önerilmez, bu sadece bir demo örneği içindir.

#!/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)

Bu, aşağıdaki sonucu verecektir -

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 ve Ruby

XML'i görüntülemenin alternatif bir yolu XPath'dir. Bu, bir XML belgesindeki belirli öğelerin ve özniteliklerin nasıl konumlandırılacağını açıklayan ve bu belgeyi mantıksal sıralı bir ağaç olarak ele alan bir tür sözde dildir.

REXML, XPath sınıfı aracılığıyla XPath desteğine sahiptir . Yukarıda gördüğümüz gibi ağaç temelli ayrıştırmayı (belge nesne modeli) varsayar.

#!/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

Bu, aşağıdaki sonucu verecektir -

<movie title = 'Enemy Behind'> ... </>
War, Thriller
Anime, Science Fiction
Anime, Action
Comedy
["DVD", "DVD", "DVD", "VHS"]

XSLT ve Ruby

Ruby'nin kullanabileceği iki XSLT ayrıştırıcısı vardır. Her birinin kısa bir açıklaması burada verilmiştir.

Ruby-Sablotron

Bu ayrıştırıcı, Masayoshi Takahashi tarafından yazılır ve sürdürülür. Bu, öncelikle Linux işletim sistemi için yazılmıştır ve aşağıdaki kitaplıkları gerektirir -

  • Sablot
  • Iconv
  • Expat

Bu modülü şu adreste bulabilirsiniz: Ruby-Sablotron.

XSLT4R

XSLT4R, Michael Neumann tarafından yazılmıştır ve RAA'da, XML altındaki Kitaplık bölümünde bulunabilir. XSLT4R, basit bir komut satırı arayüzü kullanır, ancak alternatif olarak bir XML belgesini dönüştürmek için üçüncü taraf bir uygulamada da kullanılabilir.

XSLT4R'nin çalışması için, XSLT4R arşivinde bulunan ve aynı zamanda yüzde 100 Ruby modülü olan XMLScan'e ihtiyacı vardır. Bu modüller, standart Ruby kurulum yöntemi (yani, ruby ​​install.rb) kullanılarak kurulabilir.

XSLT4R aşağıdaki sözdizimine sahiptir -

ruby xslt.rb stylesheet.xsl document.xml [arguments]

XSLT4R'yi bir uygulama içinden kullanmak istiyorsanız, XSLT'yi dahil edebilir ve ihtiyacınız olan parametreleri girebilirsiniz. İşte örnek -

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 )

Daha fazla okuma

  • REXML Ayrıştırıcı hakkında eksiksiz bir ayrıntı için, lütfen REXML Ayrıştırıcı Belgeleri için standart belgelere bakın .

  • XSLT4R'yi RAA Deposundan indirebilirsiniz .