LINUXSOFT.cz Přeskoč levou lištu
Uživatel: Heslo:  
   CZUKPL

> Ruby VIII.

Tentokrát se podíváme, jak zpracovat soubory XML pomocí jazyka Ruby

28.4.2012 21:00 | Jakub Lares | Články autora | přečteno 2153×

Základy práce s XML

XML nemá předem daná pravidla pro reprezentaci datových struktur - tyto struktury musíme sami navrhnout a implementovat. Výhodou je o něco větší flexibilita tohoto datového formátu a možnost nadefinovat si skutečně libovolné struktury přesně odpovídající datové doméně. Pomocí knihovny REXML nejdříve vytvoříme XML dokument s kořenovým elementem data, ve kterém jsou jednotlivé položky pole uložené ve vnořených elementech animal. Toto XML zapíšeme do řetězce, který potom následně opět pomocí knihovny REXML načteme, a převedeme zpět na původní pole. Zde, nalezneme soubory, se kterými budeme dneska pracovat.

 require 'rexml/document'
# Vstupni data
data = ['Cat', 'Dog', 'Elepahnt']
puts 'Input data:'
p data

# Vytvorit novy XML dokument
doc = REXML::Document.new
# Vlozit hlavicku
doc << REXML::XMLDecl.new
# Vytvorit korenovy element 'data'
root = REXML::Element.new('data')
# Iterovat pres data
data.each do |value|
  # Vytvorit novy element 'animal'
  new_element = REXML::Element.new('animal')
  # VLozit do elementu text (jmeno zvirete)
  new_element.text = value
  # Pridat novy element do korenoveho elementu
  root.elements << new_element
end
# Vlozit korenovy element do dokumentu
doc.elements << root
xml = ""
# Zapsat XML dokument do retezce xml
doc.write(xml,2,false)
puts "Converted to XML"
puts xml

# Parsovani XML
data2 = []
# Nacist retezec xml do dokumentu doc2
doc2 = REXML::Document.new(xml)
# Iterovat pres elementy v korenovem elementu
doc2.root.elements.each do |element|
  # Vlozit do pole textovy obsah elementu (orezat bile znaky)
  data2 << element.text.strip
end
puts "Parsed from XML:"
p data2

Výstup
Input data:
["Cat", "Dog", "Elepahnt"]
Converted to XML
<?xml version='1.0'?>
<data>
  <animal>
    Cat
  </animal>
  <animal>
    Dog
  </animal>
  <animal>
    Elepahnt
  </animal>
</data>
Parsed from XML:
["Cat", "Dog", "Elepahnt"]

Vytvoření XML pomocí knihovny REXML

V tomto příkladu zkusíme do XML zapsat datovou strukturu ze souboru quiz_object.yaml. Načtení této datové struktury do objektů provedeme metodou YAML.load_file. Aby toto načtení fungovalo, tak musíme mít přístupné definice příslušných tříd - o toto se stará příkaz require. REXML API pro vytváření XML je poměrně jednoduché, je to kombinace vytváření nových elementů pomocí Element.new, nastavování atributů elementům pomocí přístupové metody attributes, a vkládání podřazených elementů operátorem << do pole elements. Výsledné XML se uloží do souboru voláním doc.write.

 require 'rexml/document'
require 'yaml'
# Musime nacist soubor s tridami Quiz, Question a Answer
require 'quiz_classes'

source_file = 'quiz_object.yaml'
target_file = 'quiz_object_rexml.xml'

# Nahrat YAML data kvizu do quiz_object
quiz_object = YAML.load_file(source_file)
puts "Quiz data loaded from #{source_file}"

# Vytvorit novy dokument
doc = REXML::Document.new
doc &lt;&lt; REXML::XMLDecl.new
# Vytvorit korenovy element
root = REXML::Element.new('quiz')
# Nastavit atributy
root.attributes['name'] = quiz_object.name
root.attributes['author'] = quiz_object.author
# Iterovat pres otazky
quiz_object.questions.each do |question|
  # Vytvorit novou otazku
  new_question = REXML::Element.new('question')
  new_question.attributes['text'] = question.text
  # Iterovat pres odpovedi
  question.answers.each do |answer|
    # Vytvorit novou odpoved
    new_answer = REXML::Element.new('answer')
    # Nastavit text uvnitr elementu
    new_answer.text = answer.text
    # Pokud je odpoved pravdiva, tak nastavit hodnotu na "1"
    correct = "0"
    correct = "1" if answer.correct
    new_answer.attributes['correct'] = correct
    # Element odpoved vlozit do elementu otazka
    new_question.elements &lt;&lt; new_answer
  end
  # Vlozit otazku do korenoveho elementu
  root.elements &lt;&lt; new_question
end
# Vlozit korenovy element do dokumentu
doc.elements &lt;&lt; root
# Zapsat XML do souboru
File.open("quiz_object_rexml.xml","w") do |file|
  doc.write(file,2)
end

puts "Quiz data written to #{target_file}"
puts

File.open(target_file,"r") do |file|
  file.each_line do |line|
    puts line
  end
end


Výstup
 Quiz data loaded from quiz_object.yaml
Quiz data written to quiz_rexml.xml

<?xml version='1.0'?>
<quiz name='Test vseobecnych znalosti' author='Tomas Marny'>
  <question text='Hlavni mesto San Marina?'>
    <answer correct='0'>
      Torino
    </answer>
    <answer correct='1'>
      San Marino
    </answer>
    <answer correct='0'>
      Vatikan
    </answer>
    <answer correct='0'>
      Terst
    </answer>
  </question>
...

Vytvoření XML pomocí knihovny Builder

Stejné XML jako v předchozím příkladu můžeme o něco úsporněji vytvořit pomocí knihovny builder. Pokud tuto knihovnu nemáte, tak si ji nainstalujte v NetBeans v menu Tools > Ruby Gems > New Gems > Search: builder. Knihovna builder nabízí oproti REXML o něco úspornější API, které využívá dynamických vlastností jazyka Ruby. XML vytváříme voláním metod na objektu Builder::XmlMarkup, kde jméno volané metody je přímo jménem vytvářeného elementu, a případný textový obsah a atributy elementu se předají jako parametry této metody. Pro odlišení speciální metody (jako např instruct! pro vložení XML hlavičky) končí vykřičníkem. XML se zapisuje přímo do souboru, který jsme předali objektu Builder::XmlMarkup v parametru target.

 require 'rubygems'
require 'builder'
require 'yaml'
# Musime nacist soubor s tridami Quiz, Question a Answer
require 'quiz_classes'

source_file = 'quiz_object.yaml'
target_file = 'quiz_object_builder.xml'

# Nahrat YAML data kvizu do quiz_object
quiz_object = YAML.load_file(source_file)
puts "Quiz data loaded from #{source_file}"

# Otevrit cilovy soubor
File.open(target_file,'w') do |file|
  # Vytvorit novy XML dokument
  xml = Builder::XmlMarkup.new({:target =&gt; file, :indent =&gt; 2})
  # Vlozit hlavicku
  xml.instruct!
  # Vytvorit korenovy element 'quiz' vcetne atributu
  xml.quiz({'name' =&gt; quiz_object.name, 'author' =&gt; quiz_object.author}) do
    # Iterovat pres otazky
    quiz_object.questions.each do |question|
      # Vytvorit zde (uvnitr xml elementu quiz) element question
      xml.question({'text' =&gt; question.text}) do
        # Iterovat pres odpovedi
        question.answers.each do |answer|
          # Zapsat 1 do atributu correct pokud je odpoved spravna
          correct = 0
          correct = 1 if answer.correct
          # Vytvorit zde element answer
          xml.answer(answer.text, {'correct' =&gt; correct})
        end # Konec iterace answers
      end # Konec elemetu question
    end # Konec iterace pres quiestions
  end # Konec elementu quiz
end # Zavrit soubor

puts "Quiz data written to #{target_file}"
puts

File.open(target_file,"r") do |file|
  file.each_line do |line|
    puts line
  end
end

Výstup
 Quiz data loaded from quiz_object.yaml
Quiz data written to quiz_builder.xml
<?xml version="1.0" encoding="UTF-8"?>
<quiz name="Test vseobecnych znalosti" author="Tomas Marny">
  <question text="Hlavni mesto San Marina?">
    <answer correct="0">Torino</answer>
    <answer correct="1">San Marino</answer>
    <answer correct="0">Vatikan</answer>
    <answer correct="0">Terst</answer>
  </question>
...

Načítání XML pomocí stromového rozhraní

V tomto příkladu načítáme XML stejným způsobem jako v prvním příkladu, pouze se jedná trochu složitější soubor. Čteme právě to XML, které jsme vytvořili v minulém příkladu. Základem jsou dvě vnořené smyčky, z nichž jedna iteruje přes otázky (root.elements) a druhá přes odpovědi (question.elements). V průběhu iterace vytváříme výsledné objekty. Seznam otázek vypíšeme metodou print_quiz.

 require 'rexml/document'
require 'yaml'
# Musime nacist soubor s tridami Quiz, Question a Answer
require 'quiz_classes'

source_file = 'quiz_builder.xml'
puts "Parsing source file #{source_file}"

File.open(source_file,"r") do |file|
  # Otevrit soubor jako XML dokument
  doc = REXML::Document.new(file)
  # Precist jmeno a autora z atributu korenoveho elementu
  name = doc.root.attributes['name']
  author = doc.root.attributes['author']
  # Vytvorit novy Quiz objekt
  quiz = Quiz.new(name,author,Array.new)
  # Iterovat pres vnitrni elementy korenoveho elementu
  doc.root.elements.each do |question|
    # Vytvorit novy Question objekt, vlozit text z atributu
    new_question = Question.new(question.attributes['text'],Array.new)
    # Iterovat pres vnitrni elementy elementu 'question'
    question.elements.each_with_index do |answer,i|
      # Zjistit jestli je otazka spravna a pripadne prevest "1" na true
      correct = false
      correct = true if answer.attributes['correct']=="1"
      # Pridat do objektu otazky novou odpoved
      new_question.answers &lt;&lt; Answer.new(answer.text.strip,correct)
    end
    # Pridat novou otazku do kvizu
    quiz.questions &lt;&lt; new_question
  end
  # Vytisknout kviz
  quiz.print_quiz
end


Výstup
 Parsing source file quiz_builder.xml
Test vseobecnych znalosti
Tomas Marny
1. Hlavni mesto San Marina?
a) Torino
b) San Marino
c) Vatikan
d) Terst

Soubory ke stažení

RAR archív s příklady

Závěr

Toto je pro dnešek vše, příště si řekneme něco o unit testech a dokumentaci.

Verze pro tisk

pridej.cz

 

DISKUZE

Nejsou žádné diskuzní příspěvky u dané položky.



Příspívat do diskuze mohou pouze registrovaní uživatelé.
> Vyhledávání software
> Vyhledávání článků

28.11.2014 7:08 /MaReK Olšavský
Blížící víkend lze využít i na prozkoumání nové verze Battle for Wesnoth 1.12, která přináší především vylepšení ve správě add-ons. Instalace, na konci, je zatím napsána pro sestavení ze zdrojových kódů.
Přidat komentář

28.11.2014 7:08 /MaReK Olšavský
Alternativní ReactOS potkalo několik novinek, z nichž je nejvidětelnější nový Explorer (podobný tomu z Windows 2003), ale i prvního placeného vývojáře. Snad se jednou dočkáme produkční verze systému s nativním Win-API.
Přidat komentář

27.11.2014 7:10 /MaReK Olšavský
Malý desktop s distribucí Ubuntu a použitelným dostatkem RAM, to vše se SoC rodiny Cortex-A9, představila začínající společnost „Imp“. Cena do US$ 200,— je příjemná a dnes už by měl takto „slabý“ počítač dostačovat běžným uživatelům.
Přidat komentář

27.11.2014 7:10 /MaReK Olšavský
Na MeetBSD California 2014 prezentoval Jordan Hubbard plány pro příštích 10 let, ve vývoji FreeBSD. Operuje se s pojmy BYOD, cloud, virtualizace. Po výrazné finanční injekci a nasazení na Sony PS4 to vypadá na oživení projektu, jehož svobodný předchůdce tu byl dříve, než dnešní GNU/Linux (který již není možné považovat za alternativní OS).
Přidat komentář

27.11.2014 7:10 /MaReK Olšavský
O rozdílech mezi prohlížeči Google Chrome a Chromium nemá hodně uživatelů jasno, často je Chromium popisováno jen slovy „otevřená verze Chrome“. Stručné vysvětlení ukáže, kolik toho je, co Google nechává jako uzavřené kódy, většinou jde o technologie, které sice smí používat, ale nesmí je zveřejnovat.
Přidat komentář

26.11.2014 7:10 /MaReK Olšavský
Vyšel fork FreeBSD, DragonglyBSD 4.0, který je pouze ve verzi x86-64 (a 32 bitová verze ani není naplánována), zvedá limit souběžně podporovaných procesorů na 256, nebo vylepšuje podporu OpenGL renderování.
Přidat komentář

24.11.2014 7:19 /MaReK Olšavský
O přízeň uživatelů kodeků se uchází 2 balíky, FFmpeg a Libav (který je forkem FFmpeg, vzniklým v roce 2011).Mainstreamové distribuce, jako Debian, Ubuntu, nebo Fedora, používají Libav, ale Ubuntu by se mělo vrátit k FFmpeg, počínaje verzí 15.04. Ubuntu tímto činí další krok, který je nezávislý na mateřské distribuci Debian.
Přidat komentář

24.11.2014 7:19 /MaReK Olšavský
Blíží se dlouhé zimní večery a Steam přichází s nabídkou simulátoru kozy :-) za příjemných 9,99 €, samozřejmě i ve verzi pro GNU/Linux. Kolik toho zvládne jedna koza sežrat a zničit?
Přidat komentář

   Více ...   Přidat zprávičku

> Poslední diskuze

11.11.2014 14:24 / Libor Suchý
Nekonečný while cyklus

10.11.2014 19:09 / Libor Suchý
Re: tabulka - bitovy sucet

10.11.2014 19:03 / Libor Suchý
Re: tabulka - bitovy sucet

24.10.2014 17:47 / Petr Ježek
Andreas

16.10.2014 7:56 / Leo
Sanba

Více ...

ISSN 1801-3805 | Provozovatel: Pavel Kysilka, IČ: 72868490 (2003-2014) | mail at linuxsoft dot cz | Design: www.megadesign.cz | Textová verze | zákony online