• Coding
  • [Exercise] Vanilla XML Builder

With the language of your choice, create an XML Builder that adheres to the vanilla rules of XML.

Semi Pseudo
auditorium = Node(tag: "Auditorium")

john  = Node(tag="Person", attr={ name: "john", sex: "male"})
jane  = Node(tag="Person", attr={ name: "jane", sex: "female"})
rahmu = Node(tag="Person", attr={ name: "rahmu", sex: "undetermined"})

auditorium.children.add([john,jane,rahmu])

auditorium.flush(out_stream)
Output
<Auditorium>
<Person name="john" sex="male"/>
<Person name="jane" sex="female"/>
<Person name="rahmu" sex="undetermined"/>
</Auditorium>
Use anything at your disposal.
The code could look much better and needs some checks, it could be much more efficient and elegant as well.
It's doing the job, so I'm guessing that should count for something.

The assumption is that the tags will self-close when they don't have children.

Ruby
class Node
    
    attr_accessor :tag, :attr, :children
    
    def initialize( tag, attr )
        @tag = tag
        @attr = attr
        self.children = []
    end
    
    def add_children( children )
        # add check to make sure they are nodes
        children.each do |c|
            self.children << c
        end
    end
    
    def has_children?
        self.children != [] ? true : false
    end
    
    def print_all
        
       if self.has_children? == true
           self.print_open( true )
           self.children.each do |c|
               c.print_all
           end
           self.print_close
       else
           self.print_open( false )
       end 
    end
    
    def print_open( children_flag )
        if self.attr != {}
            print "<#{tag} "
            self.attr.each{ |k,v| print "#{k}=\"#{v}\" " }
            print children_flag ? ">\n" : "/>\n"
        else
            puts children_flag ? "<#{tag}>" : "<#{tag} />"
        end
    end
    
    def print_close
        puts "</#{tag}>"
    end
    
end

auditorium = Node.new( "Auditorium", {} )

roula = Node.new( "Person", { :name => "roula", :sex => "female" } )
omar = Node.new( "Person", { :name => "omar", :sex => "male" } )
raul = Node.new( "Baby", { :name => "raul", :sex => "male" })

auditorium.add_children( [roula, omar] )
omar.add_children( [raul] )
auditorium.print_all
<Auditorium>
<Person name="roula" sex="female" />
<Person name="omar" sex="male" >
<Baby name="raul" sex="male" />
</Person>
</Auditorium>
function Node(tag, attr) {
	this.tag = tag;
	this.attr = attr;
	this.children = [];
}

Node.prototype.print = function () {
	print(this.xml_string());
};

Node.prototype.xml_string = function () {
	var attr_string = function (attr) {
		var s = '';
		for (var a in attr) {
			s += ' ' + a + '="' + attr[a] + '"';
		}
		return s;
	};

	var s = '';
	if (this.children.length > 0) {
		s += '<' + this.tag +  attr_string(this.attr) + '>';
		for (var i = 0; i < this.children.length; i++) {
			s += this.children[i].xml_string();
		}
		s += '</' + this.tag + '>';
	} else {
		s += '<' + this.tag +  attr_string(this.attr) + '/>';
	}
	return s;
};

var group = new Node('group', {});
group.children.push(new Node('person', {name: 'foo', sex: 'm'}));
group.children.push(new Node('person', {name: 'bar', sex: 'f'}));
group.children.push(new Node('person', {name: 'baz', sex: 'z'}));
group.children.push(new Node('person', {name: 'qux', sex: 'u'}));
group.print();
Shouldn't we use some language descriptor: Ruby and JS for the above examples?
samer,

It works, but with ruby's language feature you should do better. Try to implement it using the builder concept, it would look awesome.

As in, write the builder.
xterm wrotesamer,

It works, but with ruby's language feature you should do better. Try to implement it using the builder concept, it would look awesome.

As in, write the builder.
It seems that the method_missing could do the trick to pull something like this off:

Ruby
builder = Builder.new( … )
builder.auditorium{ |build|
  build.name("Omar");
  build.gender("Male");
}
I'll try to work on it, ASAP.
Vanilla rules of XML... what's that? You got me confused now after failing to look it up on Google!

I read the XML you posted 'normal'.

Correct me please! or provide some definition for what you call Vanilla rules of XML.