README.rdoc in Empact-roxml-2.4.3 vs README.rdoc in Empact-roxml-2.5.1

- old
+ new

@@ -12,40 +12,40 @@ ROXML, you can annotate the Ruby classes as follows: class Book include ROXML - xml_reader :isbn, :attr => "ISBN" # attribute with name 'ISBN' - xml_reader :title - xml_reader :description, :as => :cdata # text node with cdata protection - xml_reader :author + xml_accessor :isbn, :from => "@ISBN" # attribute with name 'ISBN' + xml_accessor :title + xml_accessor :description, :cdata => true # text node with cdata protection + xml_accessor :author end class Library include ROXML - xml_accessor :name, :from => "NAME", :as => :cdata - xml_accessor :books, [Book], :in => "books" + xml_accessor :name, :from => "NAME", :cdata => true + xml_accessor :books, :as => [Book] # by default roxml searches for books for in <book> child nodes, then, if none are present, in ./books/book children end To create a library and put a number of books in it we could run the following code: - book = Book.new() + book = Book.new book.isbn = "0201710897" book.title = "The PickAxe" book.description = "Best Ruby book out there!" book.author = "David Thomas, Andrew Hunt, Dave Thomas" - lib = Library.new() + lib = Library.new lib.name = "Favorite Books" - lib << book + lib.books = [book] To save this information to an XML file: - File.open("library.xml", "w") do |f| - lib.to_xml.write(f, 0) - end + doc = ROXML::XML::Document.new + doc.root = lib.to_xml + doc.save("library.xml") To later populate the library object from the XML file: lib = Library.from_xml(File.read("library.xml")) @@ -60,15 +60,26 @@ </publisher> </book> can be mapped using the following code: + class Publisher + include ROXML + + xml_accessor :name + + # other important functionality + end + class BookWithPublisher include ROXML - xml_name :book - xml_reader :publisher, Publisher + xml_name 'book' + xml_reader :publisher, :as => Publisher + + # or, alternatively, if no class is needed to hang functionality on: + # xml_reader :publisher, :from => 'name', :in => 'publisher' end Note: In the above example, _xml_name_ annotation tells ROXML to set the element name to "book" for mapping to XML. The default is XML element name is the class name in lowercase; "bookwithpublisher" in this case. @@ -76,37 +87,48 @@ == Manipulation Extending the above examples, say you want to parse a book's page count and have it available as an Integer. In such a case, you can extend any object with a block to manipulate it's value at parse time. For example: - class Child + class Dog include ROXML - xml_reader :age, :attr do |val| - Integer(val) - end + xml_reader(:age, :from => '@human_years', :as => Integer) {|years| years * 7 } end The result of the block above is stored, rather than the actual value parsed from the document. == Construction -Complicated initialization may require action on multiple attributes of an object. As such, you can -define method xml_initialize to perform initialization after instantiation and parsing, including -causing your ROXML object to call its own constructor, as in the following: +Object life-cycle is as follows: .from_xml is called with a first argument representing the xml +in file, string, or path form, and with optional initialization_args following. +Firt .new and thus #initialize, is called with those same initialization_args, or no args if none +are present. Then the object is populated with the attribute values from xml. Then the +#after_parse callback is called, with no arguments. + +In #after_parse you can ensure that your object initialization is complete, including initialization which +requires more than one variable in concert. + +E.g.: + class Measurement include ROXML - xml_reader :units, :attr - xml_reader :value, :content + xml_reader :units, :from => :attr + xml_reader :value, :from => :content - def xml_initialize + def initialize(value = 0, units = 'meters') + to_metric + end + + private + def after_parse # xml attributes of self are already valid - initialize(value, units) + to_metric end - def initialize(value, units) + def to_metric # translate units & value into metric, for example end end One important use of this approach is to make ROXML object which may or may not include an xml backing,