AXML

AXML - Provides a simple DOM for working with XML (using XMLParser under the hood) that can serve as a drop in replacement for a subset of basic libxml functionality (e.g., each, children, child, find_first, find, next).

‘AXML’ means ‘ax XML’ which succinctly describes the occasional feeling of a programmer towards XML or its myriad parsers. AXML won’t solve all your problems, but it does make working with XML much less painful.

Features


  • fast: it’s implemented in XMLParser (expat under the hood)

  • lean: as in ‘lines of code’ (~220 w/ blank lines) and as in ‘memory consumption’ (nodes implemented as Struct, children in Array)

  • *easy to extend*: code your Grandmother could read and understand (if she reads ruby)

  • *quacks like libxml*: implements a very useful subset of libxml methods for near drop in replacement.

Examples


require 'axml'  # currently requires 'xmlparser' be installed
                # Windows: already in one-click-installer
                # Ubuntu: sudo apt-get install libxml-parser-ruby1.8
                # Cygwin: see http://mspire.rubyforge.org/tutorial/cygwin_mspire.html

# a little example xml string to use
string_or_io = "
<n1>
  <n2 size='big'>
    <n3>words here</n3>
    <n3></n3>
  </n2>
  <n2 size='small'>
    <n3 id='3'></n3>
  </n2>
</n1>
"

### Read a string or io

n1_node = AXML.parse(string_or_io)

### Read a file

n1_node = AXML.parse_file('path/to/file')

### Access children

n1_node.children # -> [array]
n1_node.each {|child|  # do something with child }

### Get attributes and text

n2_node['size'] == 'big'
n3_node = n2_node.child
n3_node.text    # -> 'words here'
n3_node.content # -> [same]

### Traverse nodes with next and child

n2_node = n1_node.child
the_other_n2_node = n2_node.next
the_other_n2_node.next = nil

### Does a little xpath

# find_first (returns the first node)
n3_node = n1_node.find_first('descendant::n3')
other_n3_node = n3_node.find_first('following-sibling::n3')
n1_node.find_first('child::n3')    # -> nil

# find (returns an array)
n1_node.find('descendant::n3')     # -> [array of all 3 <n3> nodes]
n1_node.find('child::n2')          # -> [array of 2 <n2> nodes]

### Switch to libxml

This is all it takes to get all of the above code to work under libxml:

require 'xml/libxml'   # instead of:  require 'axml'

# A file
REPLACE: n1_node = AXML.parse_file(file)
WITH:    n1_node = XML::Document.file(file).root          # note the .root call on the end!

# A string
REPLACE: n1_node = AXML.parse(string)
WITH:    n1_node = XML::Parser.string(string).parse.root  # note the .root call on the end!

Wallah! All the above method calls work under libxml

See ‘specs/axml_spec.rb` for more examples and functionality

Detailed Description


Parses elements, attributes, and text(content), and nothing more. Should be very easy to extend and modify for special cases. It is roughly as fast as libxml, although it currently reads in the entire document first (however, this is memory efficient - nodes are implemented using Struct).

Installation


gem install axml