Skip to content

Writing XML Documents

yeban edited this page Apr 17, 2011 · 2 revisions

Note: This was written a year back, and needs to be checked against git head.

Creating an XML document with Ruby libxml binding is very intuitive. API docs are good. Documentation for the XML::Document class is a good point to start.

Consider the code below as a "Hello World" example. The code in in itself is self explanatory.

require "rubygems"
require "xml"

#add a list of namespaces to the node
#the namespaces formal parameter is a hash
#with "prefix" and "prefix_uri" as
#key, value pairs
#prefix for the default namespace is "default"
def add_namespaces( node, namespaces )
  #pass nil as the prefix to create a default node
  default = namespaces.delete( "default" )
  node.namespaces.namespace = XML::Namespace.new( node, nil, default )
  namespaces.each do |prefix, prefix_uri|
    XML::Namespace.new( node, prefix, prefix_uri )
  end
end

#add a list of attributes to the node
#the attributes formal parameter is a hash
#with "name" and "value" as
#key, value pairs
def add_attributes( node, attributes )
  attributes.each do |name, value|
    XML::Attr.new( node, name, value )
  end
end

#create a node with name
#and a hash of namespaces or attributes
#passed to options
def create_node( name, options )
  node = XML::Node.new( name )

  namespaces = options.delete( :namespaces )
  add_namespaces( node, namespaces ) if namespaces

  attributes = options.delete( :attributes )
  add_attributes( node, attributes ) if attributes
  node
end

doc = XML::Document.new
doc.encoding = XML::Encoding::ISO_8859_1

root = create_node("nexml",
                   :namespaces => { "default" => "http://www.nexml.org/1.0",
                                    "xsi" => "http://www.w3.org/2001/XMLSchema-instance",
                                    "xlink" => "http://www.w3.org/1999/xlink",
                                    "nex" => "http://www.nexml.org/1.0",
                                  },
                   :attributes => { "xsi::schemaLocation" =>
                                    "http://www.nexml.org/1.0 ../xsd/nexml.xsd",
                                    "generator" => "mesquite",
                                    "version" => "0.8"
                                  }        
                  )
default = root.namespaces.find_by_prefix( "nex" )
root.namespaces.namespace = default
doc.root = root #mark if as the root node of the doc

otus = create_node("otus",
                   :attributes => { "id" => "taxa1",
                                    "label" => "My taxa block",
                                    "xml:base" => "http://example.org/",
                                    "xml:id" => "taxa1",
                                    "class" => "taxset1",
                                    "xml:lang" => "EN" 
                                  }
                  )
root << otus #otus will be a child node of root

#create a comment node for otus
comment = <<EOF
                        The taxon element is analogous to a single label in 
			a nexus taxa block. It may have the same additional
			attributes (label, xml:base, xml:lang, xml:id, xlink:href
			and class) as the taxa element.
EOF
comment_node = XML::Node.new_comment( comment )
otus << comment_node

#create five child nodes( otu ) for the otus element
5.times do | i |
  otu = create_node("otu", :attributes => { "id" => "t#{i+1}" })
  otus << otu
end

doc.save( "sample.xml", :indent => true )

The above code produces an XML file on the following lines( the only difference will be in the indentation of the attributes ):

<?xml version="1.0" encoding="ISO-8859-1"?>
<nex:nexml 
	version="0.8"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://www.nexml.org/1.0 ../xsd/nexml.xsd"
	xmlns:nex="http://www.nexml.org/1.0"
	generator="mesquite"
	xmlns:xlink="http://www.w3.org/1999/xlink"
	xmlns="http://www.nexml.org/1.0">
	<otus 
		id="taxa1" 
		label="My taxa block" 
		xml:base="http://example.org/" 
		xml:id="taxa1" 
		class="taxset1" 
		xml:lang="EN" 
		xlink:href="#taxa1">
		<!--  
			The taxon element is analogous to a single label in 
			a nexus taxa block. It may have the same additional
			attributes (label, xml:base, xml:lang, xml:id, xlink:href
			and class) as the taxa element.
		-->
		<otu id="t1"/>
		<otu id="t2"/>
		<otu id="t3"/>
		<otu id="t4"/>
		<otu id="t5"/>
	</otus>
</nex:nexml>
Clone this wiki locally