Install the Ox gem
developInstall the Ox gem using the standard Ruby gem command.
gem install oxrepository·develop·Indexed 21 days ago
https://github.com/ohler55/oxOx is a high-performance XML parser and Object marshaller for Ruby, designed as a faster alternative to Nokogiri for XML/HTML parsing and a human-readable alternative to Ruby's native Marshal for object serialization. It supports generic XML writing and parsing via Ox::Document and Ox::Element, high-performance stream parsing using a SAX API (Ox::Sax), and the ability to convert XML into Ruby Hashes. Ox also provides a simplified path-based node location system and an 'easy' API for navigating XML structures.
Install the Ox gem using the standard Ruby gem command.
gem install oxThe Ox::HasAttrs module provides an 'easy' API for interacting with XML attributes. Objects including this module treat attributes as a Hash where keys can be either String or Symbol.
Key capabilities include:
[] to retrieve values by name.method_missing to access attributes as if they were method calls (e.g., node.id).attributes to get all attributes as a Hash.[]= to set or add attributes.Note: When setting attributes via []=, the value is automatically converted to a String.
# Assuming an object 'node' includes Ox::HasAttrs
# 1. Accessing attributes
val = node[:id] # Using Symbol
val = node['id'] # Using String
val = node.id # Using method-style access
# 2. Setting attributes
node[:class] = 'container'
node['type'] = 'header'
# 3. Getting all attributes
all_attrs = node.attributes # Returns a HashFor simple, regularly formatted XML, you can navigate the document tree by calling methods named after the element or attribute names directly on the Ox::Element object.
element.Name(1)..text method to retrieve the first String node within an element's children.Note: This API raises a NoMethodError if the requested name is not found.
doc = Ox.parse(%{
<?xml?>
<People>
<Person age="58">
<given>Peter</given>
<surname>Ohler</surname>
</Person>
<Person>
<given>Makie</given>
<surname>Ohler</surname>
</Person>
</People>
})
# Accessing elements and attributes via method calls
doc.People.Person.given.text # => "Peter"
doc.People.Person(1).given.text # => "Makie"
doc.People.Person.age # => "58"Ox operates in two distinct modes depending on your requirements:
Marshal. It is optimized for speed when converting Ruby objects to XML and back.You can track the parser's position within the XML document by initializing specific instance variables in your Ox::Sax subclass's initialize method. The parser will automatically update these variables before each callback is invoked:
@line: Updated with the current XML line number.@column: Updated with the column number where the current element or node starts.@pos: If defined, updated with the number of bytes from the start of the document.class MySax < ::Ox::Sax
def initialize
@line = 0
@column = 0
@pos = 0
end
def start_element(name)
puts "Starting element #{name} at line #{@line}, col #{@column}, byte #{@pos}"
end
endAll errors raised by the Ox gem inherit from Ox::Error. You can use this as a catch-all rescue clause to handle any library-specific exceptions.
begin
# Ox operation
rescue Ox::Error => e
puts "An Ox error occurred: #{e.message}"
endOx provides a SAX (Simple API for XML) parser for event-based XML parsing, which is ideal for processing very large files or IO streams without loading the entire document into memory.
To use it, you must create a subclass of Ox::Sax and implement the specific callback methods you wish to trigger. These methods must be public in your subclass; if they remain private, the parser will not call them.
Argument Types:
name arguments are passed as Symbol.str arguments are passed as String.value arguments are passed as Ox::Sax::Value objects.Callback Overlap Rules:
value(value) public, the text(str) method will be ignored for that element.attr_value(name, value) public, the attr(name, str) method will be ignored.attrs_done() callback is invoked once all attributes for an element have been read.require 'ox'
class MySax < ::Ox::Sax
def initialize
@element_names = []
end
def start_element(name)
@element_names << name
end
end
any = MySax.new()
File.open('any.xml', 'r') do |f|
Ox.sax_parse(any, f)
endThe Ox::Bag class is a generic container used by the Ox storage system to hold attributes for auto-generated classes. It is designed to be read-only; instance variables are added via instance_variable_set, but no explicit setters are provided.
Attributes can be accessed as if they were methods (without the @ prefix). For example, if an instance variable is named :@x, you can access it by calling .x on the object.
Note: The initialize method accepting a hash of instance variable symbols is intended for testing purposes only.
# For testing purposes: creating a bag with specific instance variables
bag = Ox::Bag.new(:@x => 42, :@y => 57)
puts bag.x # => 42
puts bag.y # => 57Because HTML is often non-conforming, you should adjust the Ox.default_options to use :generic mode with :tolerant effort and smart: true to handle loose HTML structures.
Ox.default_options = {
mode: :generic,
effort: :tolerant,
smart: true
}You can use Ox::StreamParser as a high-performance alternative to the standard library's XML-RPC parser. It is based on REXMLStreamParser but utilizes the Ox engine for parsing. To use it, require both xmlrpc/client and ox/xmlrpc_adapter, then pass a new instance of Ox::StreamParser to your XML-RPC client using set_parser.
require 'xmlrpc/client'
require 'ox/xmlrpc_adapter'
client = XMLRPC::Client.new2('http://some_server/rpc')
client.set_parser(Ox::StreamParser.new)Ox provides a way to build XML documents programmatically using Ox::Document, Ox::Element, and Ox::Instruct. You can append elements to each other and add special nodes like Ox::CData, Ox::Comment, or Ox::Raw (for direct injection).
require 'ox'
doc = Ox::Document.new
instruct = Ox::Instruct.new(:xml)
instruct[:version] = '1.0'
instruct[:encoding] = 'UTF-8'
instruct[:standalone] = 'yes'
doc << instruct
top = Ox::Element.new('top')
top[:name] = 'sample'
doc << top
mid = Ox::Element.new('middle')
mid[:name] = 'second'
top << mid
bot = Ox::Element.new('bottom')
bot[:name] = 'third'
bot << 'text at bottom'
mid << bot
other_elements = Ox::Element.new('otherElements')
other_elements << Ox::CData.new('<sender>John Smith</sender>')
other_elements << Ox::Comment.new("Director's commentary")
# other_elements << Ox::DocType.new('content')
other_elements << Ox::Raw.new('<warning>Be carefull with this! Direct inject into XML!</warning>')
top << other_elements
xml = Ox.dump(doc)Ox can be used as a fast alternative to Ruby's Marshal for object serialization. It uses human-readable XML instead of a binary format. Use Ox.dump(obj) to convert an object to an XML string and Ox.parse_obj(xml) to convert the XML string back into a Ruby object.
require 'ox'
class Sample
attr_accessor :a, :b, :c
def initialize(a, b, c)
@a = a
@b = b
@c = c
end
end
# Create Object
obj = Sample.new(1, "bee", ['x', :y, 7.0])
# Now dump the Object to an XML String.
xml = Ox.dump(obj)
# Convert the object back into a Sample Object.
obj2 = Ox.parse_obj(xml)