XmlParsable

XmlParsable is a simple means to declare how an XML grammar maps to Ruby objects. It does not perform validation of the input, and it is only able to describe fairly simple structures. It relies on LibXML::XML::SaxParser.

Quick Example

For more details, see the RSpec examples in spec/examples.

Declare XML grammar

require "xmlparsable"

# Needed only for using the "collection" declaration or
# implement your own String#pluralize, String#singularize
require "active_support/core_ext"

class AddressBook
  include XmlParsable

  class Contact
    include XmlParsable
    element :givenname
    element :familyname
    element :phone
    element :email
    element :spouse,      Contact
    collection :children, Contact
    element :birthdate,   DateElement
    element :updated,     TimeElement
  end

  collection :contact, Contact
end

Parse input XML from string, IO, or File

book = AddressBook.parse(<<-XML)
  <contacts>
    <contact>
      <familyname>Kim</familyname>
      <givenname>Jong-il</givenname>
      <birthdate>1942-02-16</birthdate>
      <updated>2010-01-01T12:45:30</updated>
      <children>
        <child><givenname>Sul-song</givenname></child>
        <child><givenname>Jong-chul</givenname></child>
        <child><givenname>Jong-un</givenname></child>
        <child>
          <givenname>Jong-nam</givenname>
          <spouse>
            <givenname>Jong-hui</givenname>
            <familyname>Shin</familyname>
          </spouse>
        </child>
      </children>
    </contact>

    <contact>
      <givenname>Vladimir</givenname>
      <familyname>Putin</familyname>
      <email>[email protected]</email>
      <spouse>
        <givenname>Lyudmila</givenname>
        <familyname>Putina</familyname>
      </spouse>
    </contact>
  </contacts>
XML

Iterate parsed data

kim, vlad = book.contacts
kim.givenname #=> "Kim"
kim.birthdate #=> #<Date: 4860813/2,0,2299161>
kim.updated   #=> Fri Jan 01 12:45:30 2010

sulsong, jongchul, jongun, jongnam = kim.children
jongnam.spouse.givenname  #=> "Jong-hui"
jongnam.spouse.familyname #=> "Shin"

vlad.email    #=> "[email protected]"
vlad.spouse   #=> #<AddressBook::Contact @givenname="Lyudmila" @familyname="Putina">

Data Types

DateElement

Parses content into a Ruby Date object, using Date.parse.

ListElement

Parses children nodes into an Array using some other AbstractElement child class.

NumericElement

Parses content into a Ruby Integer or BigDecimal, depending on whether the input contains a decimal point or not. Parses using Integer(..) and BigDecimal(..) constructor methods.

RecordElement

Parses children nodes according to element and collection declarations on an XmlParsable class.

StringElement

Parses content into a Ruby String object.

TextElement

Concatenates all subordinate text nodes into a single String. For example, "abc def <b>what<!-- ever --></b>" is read as "abc def what".

TimeElement

Parses content into a Ruby Time object, using Time.parse.

XmlElement

Parses children elements into an Array whose elements are one of these three classes. These really should be the same node types that LibXML uses, but that's not the case for now.

  • XmlParsable::Elements::XmlElement::Node
  • XmlParsable::Elements::XmlElement::Text
  • XmlParsable::Elements::XmlElement::Comment