|
jan molic (MiG) http://myxml.1984.cz jan.molic {at sign} 1984 {dot} cz please report errors and enhancements, thanks |
|
| >1.0.5 | Element::add and Element::force have "auto_real" now. If you add/force element with attributes set, it defaultly becomes real. But not if auto_real=false. |
| >1.0.4 | Added methods Element::has_text?, Element::has_elements? and Element::empty? which combinate both. |
| >1.0.3 | Added method Element::empty! which delete all child elements and text of the element. |
| >1.0.2 | Added method Element::exists? which can be used to test if XML element exists already. |
| >1.0.1 | Document can be saved to another file (Document::save method). |
| >1.0 | You can add/force multiple path (element named "accounts/account" will be created before)
root.add("accounts/account") # create two elements; accounts and it's child account
|
| >1.0-r4 | Added method "hashlist" and example 10 for describing it. |
| >1.0-r3 | If add method is specified with attributes, element will be added "real". root.add("db") # not_real root.add("db", {"name"=>"aaa"} ) # real |
puts root["mailbox"]puts root["mailbox"].textmail["box/password"] = "als234"
mail["box"].attributes['a'] = "b"
puts mail["box/nonexistent"] >> ""
puts mail["box"].text >> ""
puts mail["box"].attributes['a'] >> nil
p root["mailbox"].list.each { |child| ... }p root["mailbox"].list('alias').each { |child| ... }<root> <db name='firstdb'> <user name='carl'> <password>foo</password> </user> <user name='mary'> <password>bar</password> <description> <name>Mary</name> <age>23</age> <private> <niceness>4</niceness> </private> </description> </user> </db> <defaults> <height>77</height> <width>99</width> <weight>1111</weight> </defaults> </root>
# Load, save and print test.xml require 'myxml' xml = MyXML::Document.new "test.xml" xml.done xml.save xml.write
# Find "db" element named "firstdb" and print all users
require 'myxml'
xml = MyXML::Document.new "test.xml"
firstdb = xml.root.find('db', {"name"=>"firstdb"})
firstdb.list('user').each { |e|
puts e.attributes['name']
}
# or without argument (default is '*')
firstdb.list.each { |e|
puts e.attributes['name']
}
xml.done
# Find "db" element named "firstdb",
# find user "mary" and print all her description
# (texts of first-child elements)
require 'myxml'
xml = MyXML::Document.new "test.xml"
firstdb = xml.root.find('db', {"name"=>"firstdb"})
mary = firstdb.find('user', "name"=>"mary")
mary.list("description/*").each { |e|
puts "#{e.name}: #{e}"
# or puts "#{e.name}: #{e.text}" but String behavior is easier
}
xml.done
# Set description/name of Carl
require 'myxml'
xml = MyXML::Document.new "test.xml"
firstdb = xml.root.find('db', {"name"=>"firstdb"})
carl = firstdb.find('user', {"name"=>"carl"})
carl["description/name"] = "Carl Cox"
xml.done
xml.write
# Add user Monica and set her password
require 'myxml'
xml = MyXML::Document.new "test.xml"
firstdb = xml.root.find('db', {"name"=>"firstdb"})
monica = firstdb.add('user', {"name"=>"monica"})
# until here monica not really exists !!!
monica["password"] = "123456"
xml.done
xml.write
# Add user carl if not already and
# set description/private/niceness and attribute "tip"
require 'myxml'
xml = MyXML::Document.new "test.xml"
firstdb = xml.root.find('db', {"name"=>"firstdb"})
carl = firstdb.force('user', {"name"=>"carl"})
# carl may not really exits until here
carl["description/private/niceness"] = "4"
carl.attributes["tip"] = "must see!"
xml.done
xml.write
# The same but we can use monica's password like String
require 'myxml'
xml = MyXML::Document.new "test.xml"
firstdb = xml.root.find('db', {"name"=>"firstdb"})
monica = firstdb.add('user', {"name"=>"monica"})
password = monica["password"]
# monica not exists really, so she has no password
puts "Monica's old password: " + password
password.text = "abcdef"
# !!! 'password = "abcdef"' is wrong because "abcdef" is another object (String)
# now monica is created
puts "Monica's new password: " + password
xml.done
# We can debug which elements are not really existent
# - just "print password" and see that not really exists
require 'myxml'
xml = MyXML::Document.new "test.xml"
firstdb = xml.root.find('db', {"name"=>"firstdb"})
monica = firstdb.add('user', {"name"=>"monica"})
puts monica["password"]
puts "BEFORE DONE: "
xml.write # here we can see all nonexistent elements (have attribute NOT-EXIST='true')
xml.done # elements with attribute NOT-EXIST are deleted
puts "AFTER DONE: "
xml.write # now xml is without nonexistent elements
# Delete user Carl
require 'myxml'
xml = MyXML::Document.new "test.xml"
firstdb = xml.root.find('db', {"name"=>"firstdb"})
carl = firstdb.find('user', {"name"=>"carl"})
carl["description/name"] = "Carl Cox"
carl["description/age"] = "33"
carl.delete
# !!! carl may be reused after deletion, but all children will be erased !!!
carl["password"] = "aaa"
xml.done
xml.write
# Print defaults - using hashlist
# ("hashlist" return hash {name=>element,name=>element,...}
# "list" return only [element,element,...])
require 'myxml'
xml = MyXML::Document.new "test.xml"
xml.root.hashlist('defaults/*').each {|name,e|
puts "default #{name} = #{e}"
}
xml.done
MyXML::Element.elements.findMyXML::Element.find MyXML::Element.rexml_elementputs root["mailbox"].rexml_element.name
module MyXML
class Attributes
##
# just the same as rexml_element.attributes[]
#
def []
##
# if you set attribute, rexml_element becomes real
#
def []=
end
class Elements
##
# find element
#
def find path,attributes=nil,real_only=true
##
# create parent elements if not exists (force)
# if both auto_real and attributes set, element becomes real
# add element with specified attributes
#
def add path,attributes=nil,auto_real=true
##
# like add, but element is added only if not already
# if both auto_real and attributes set, element becomes real
# already = must have specified attributes
#
def force path,attributes=nil,auto_real=true
##
# return array of child elements [element,element,...]
#
def list path='*',real_only=true
##
# return hash of child elements {element.name => element,element.name => element,...}
#
def hashlist path='*',real_only=true
end
class Element < String
attr_accessor :rexml_element
##
# see Attributes wrapper above
#
def attributes
##
# return name of element
#
def name
##
# return text of element
#
def text
##
# sets self value (String behavior)
# rexml_element becomes real
# value is converted to String
#
def text= value
##
# synonym for Elements.force_all
#
def [] path
##
# create all parential elements and
# then call text= method
#
def []= path,value
##
# rexml_element becomes not_real (is not destroyed,
# because must be reusable - be able to become real again)
def delete
##
# has element a text?
#
def has_text?
##
# has element child element(s)?
#
def has_elements?
##
# is element empty? (neither text nor child elemets exist)
#
def empty?
##
# empty this element (delete all child elements and text)
#
def empty!
##
# is this MyXML Element real? (really exists in XML?)
#
def exists?
##
# delete from rexml tree all not_real elements
# (have NOT-REAL='true' attribute)
#
def done
##
# AND ALIASES FOR METHODS IN Elements CLASS JUST FOR EASYOFUSENESS
#
end
class Document
##
# create new document from file
#
def initialize path
##
# return document root
#
def root
##
# write actual dom tree to dest
# before done "actual" means you will see all nonexistent elements!
#
def write dest=$stdout
##
# do "root.done" - delete all not_real elements
#
def done
##
# save actual dom tree to filename (> filename.tmp, synced, renamed to filename)
# or other file
#
def save other_path=nil
end
end