Ox::Builder
Ox::Builder provides a DSL for quickly building XML documents using the ox
gem.
It is intended to be a practically plug-in replacement for builder
gem for
constructing XML documents.
The DSL verbs are meant to map closely to those provided by builder
so that an existing builder template can be
ported to use Ox::Builder
with minimum effort.
In addition to providing a DSL for ox
, this library provides template handlers for action_view
and tilt
,
so that a template file can be rendered in Rails and/or via Tilt. The template handlers are activated automatically
when rendering a file named filename.ox
.
Usage
An XML document can be generated by passing a block to Ox::Builder.build
:
Ruby Code: | Generated XML: |
---|
doc = Ox::Builder.build do
instruct!
person id: 123 do
name { cdata!('John Smith') }
age 37
nationality 'Canadian'
end
end
|
<?xml version="1.0" encoding="UTF-8"?>
<person id="123">
<name>
<![CDATA[John Smith]]>
</name>
<age>37</age>
<nationality>Canadian</nationality>
</person>
|
Methods
The following methods are available within the Ox::Builder.build
DSL:
instruct!(name = :xml, attributes = { version: '1.0', encoding: 'UTF-8' })
Creates an XML processing instruction. The name or attributes can be overridden.
Ruby Code: | Generated XML: |
---|
instruct! | <?xml version="1.0" encoding="UTF-8"?> |
instruct! version: 2.0 | <?xml version="2.0"> |
instruct! 'xml-stylesheet', type: 'text/xsl', href: 'style.xsl' | <?xml-stylesheet type="text/xsl" href="style.xsl"?> |
tag!(name, content = nil, attributes = {})
Creates an arbitrary XML node with a given name and any attributes. If content is passed in, it will be inserted into the tag; otherwise the tag will be empty. A block can be given to create nested tags (and there is no limit to how deep nesting can be).
If passing content to a tag, any object can be given but note that to_s
will be called.
Nodes can also be created dynamically by name (assuming the name is a valid ruby method name). You can also append !
to the name in case there is a conflict with an existing method (see examples below).
Ruby Code: | Generated XML: |
---|
tag! :person | <person/> |
tag! :person, 'John Smith', id: '123' | <person id="123">John Smith</person> |
person 'John Smith', id: '123' | <person id="123">John Smith</person> |
person! 'John Smith', id: '123' | <person id="123">John Smith</person> |
person do
first_name, 'John'
last_name, 'Smith'
address do
country, 'Canada'
state, 'Ontario'
end
end | <person>
<first_name>John</first_name>
<last_name>Smith</last_name>
<address>
<country>Canada</country>
<state>Ontario</state>
</address>
</person>
|
Creates an XML comment with the given text.
Ruby Code: | Generated XML: |
---|
comment!('comment goes here') | <!-- comment goes here --> |
doctype!(text)
Creates a doctype element with the given text.
Ruby Code: | Generated XML: |
---|
doctype!('html') | <!DOCTYPE html > |
cdata!(text)
Create a CDATA node (ie. text wrapped in <![CDATA[]]>
)
Ruby Code: | Generated XML: |
---|
cdata! 'John Smith' | <![CDATA[John Smith]]> |
tag! :name do
cdata!('John Smith')
end | <name>
<![CDATA[John Smith]]>
<name> |
Using in a Rails view
Any view file with the extension .ox
or .xml.ox
will be picked up by Ox::Builder
and rendered as an XML file, with MIME type application/xml
. There is no setup needed to get this to work. The view should not contain Ox::Builder.build
, but rather the contents of the block that you would pass to it.
instruct!
person id: 123 do
name { cdata!('John Smith') }
age 37
nationality 'Canadian'
end
Migrating from builder
Using Ox::Builder
instead of Builder
is straightforward:
- Rename the view file from
filename.builder
to filename.ox
. - Remove any block parameters from the view code. As well, any code where the block parameter was used as a message receiver, use an implicit receiver instead.
- Remove any instances of the special
xml
receiver. declare!
is not currently supported as it's not implemented in ox
.
Therefore, the following template:
xml.people do
xml.person do |person|
person.name { xml.cdata! 'John Smith' }
person.age 37
end
end
would be converted to:
people do
person do
name { cdata! 'John Smith' }
age 37
end
end
Benchmarks
Benchmarks which compare Ox::Builder
to Builder
can be found in benchmarks/
. There are three benchmarks, for
various XML output sizes.
Small file (~170 bytes)
Calculating -------------------------------------
builder 412.000 i/100ms
ox 640.000 i/100ms
-------------------------------------------------
builder 4.230k (± 6.7%) i/s - 42.436k
ox 10.413k (±18.5%) i/s - 100.480k
Comparison:
ox: 10413.5 i/s
builder: 4230.5 i/s - 2.46x slower
Medium file (107K)
Calculating -------------------------------------
builder 1.000 i/100ms
ox 2.000 i/100ms
-------------------------------------------------
builder 11.153 (± 9.0%) i/s - 223.000
ox 23.454 (± 8.5%) i/s - 468.000
Comparison:
ox: 23.5 i/s
builder: 11.2 i/s - 2.10x slower
Huge file (11M)
Calculating -------------------------------------
builder 1.000 i/100ms
ox 1.000 i/100ms
-------------------------------------------------
builder 0.117 (± 0.0%) i/s - 8.000 in 68.435529s
ox 0.221 (± 0.0%) i/s - 14.000 in 63.819146s
Comparison:
ox: 0.2 i/s
builder: 0.1 i/s - 1.88x slower
Installation
Add this line to your application's Gemfile:
gem 'ox-builder'
And then execute:
$ bundle
Or install it yourself as:
$ gem install ox-builder
Development
After checking out the repo, run bin/setup
to install dependencies. Then, run rake spec
to run the tests. You can also run bin/console
for an interactive prompt that will allow you to experiment.
To install this gem onto your local machine, run bundle exec rake install
. To release a new version, update the version number in version.rb
, and then run bundle exec rake release
, which will create a git tag for the version, push git commits and tags, and push the .gem
file to rubygems.org.
Contributing
Bug reports and pull requests are welcome on GitHub at https://github.com/dvandersluis/ox-builder.
License
The gem is available as open source under the terms of the MIT License.