What is this?
This is a framework to create importers/exporters of XML formats for Ruby. To create a new importer/exporter all you have to do is create a ruby class for each of the XML elements.
Where do I get it?
This project is hosted on RubyForge. You can see the project page or go straight to the files section to get the latest version. If you have RubyGems installed you can just do "gem install xmlcodec" and it will fetch the latest version from the network.What features does it have?
The basic model of the framework is that an importer/exporter maps a XML tree into a Ruby object tree. To do this you write Ruby classes for each of the XML format's elements. After that you get several API's for free:
- Import/Export XML text
- Import/Export REXML DOM
- A stream parser whose events are whole elements imported into a Ruby object
- A partial export API that can be used to create huge XML files with constant memory usage
The first two API's treat the XML as a whole tree at once.
The stream parser allows you to parse a very big XML file as a stream but with more meaningfull events than a regular XML stream parser.
The partial export API allows you to create huge XML files the same way you'd create a small one (by putting elements in the Ruby tree) but without having to create the whole tree in memory. This is done by exporting an element into the output file and then removing it from the tree. This is not done automatically, but it's pretty easy to do.
How do I use it?
Look at the API docs for examples and full API of everything.Some Examples Then?
Suppose you have this XML format:
<root>
<firstelement>
<secondelement firstattr='1'>bar</secondelement>
<secondelement firstattr='2'>foo</secondelement>
</firstelement>
</root>
To create an importer/exporter for it you'd write:
require 'xmlcodec'
class Root < XMLCodec::XMLElement
elname 'root'
xmlsubel :firstelement
end
class FirstElement < XMLCodec::XMLElement
elname 'firstelement'
xmlsubel_mult :secondelement
end
class SecondElement < XMLCodec::XMLElement
elname 'secondelement'
elwithvalue
xmlattr :firstattr
end
And that's it for the code you have to write. To import some xml you'd do:
# From text
Root.import_xml_text(File.new('file.xml'))
# From a REXML DOM
Root.import_xml(REXML::Document.new(File.new('file.xml')))
To generate some XML you can do:
# To generate XML text string = some_element.xml_text # To generate REXML DOM doc = some_element.create_xml(REXML::Document.new)Using the stream parser is also very easy:
class MyStreamListener
def el_secondelement(el)
obj = el.get_object
... do something with obj ...
# To remove it from the stream so the parent
# doesn't include it and memory is freed.
el.consume
end
end
parser = XMLStreamObjectParser.new(MyStreamListener.new)
parser.parse(some_string_or_file)
The partial exporter is also pretty easy to use:
file = File.new('somefile.xml')
fe = FirstElement.new
10000.times do |i|
se = SecondElement.new(i)
fe.secondelement << se
se.partial_export(file)
end
fe.end_partial_export(file)