Wrapping XML document in Class

M

Miles Monroe

I would like to use Ruby and REXML to wrap an XML document and allow
access to the element nodes, attributes, and text. Essentially I need
an XML document builder loosely coupled from the document.

It seems like Ruby is powerful enough to code generate a class given an
XML document or build an object at run-time with the appropriate
accessors.

For instance:

order = XmlBuilder.new

order.add("root").add("header")
order.root.add("body")

order.body.add("component").attributes["type"] = "metric"

order.write($stdout)

I'd also like to be able to plug-in input validation when assigning
values to elements and attributes.

Has anyone done this before?

Thanks.
 
M

Miles Monroe

Miles said:
I would like to use Ruby and REXML to wrap an XML document and allow
access to the element nodes, attributes, and text. Essentially I need
an XML document builder loosely coupled from the document.

It seems like Ruby is powerful enough to code generate a class given an
XML document or build an object at run-time with the appropriate
accessors.

For instance:

order = XmlBuilder.new

order.add("root").add("header")
order.root.add("body")

order.body.add("component").attributes["type"] = "metric"

order.write($stdout)

I'd also like to be able to plug-in input validation when assigning
values to elements and attributes.

Has anyone done this before?

Thanks.

I found this blog entry on a XmlStringBuffer class in Ruby. I
understand using method_missing to create the element, but I'm not sure
how to closures would be implemented. Thanks.

http://www.beust.com/weblog/archives/000025.html

xml = XML.new

xml.html {
xml.head {
}
xml.body {
xml.table {
xml.tr {
xml.td({ "valign" => "top"}, "Content1"){
}
xml.td {
xml.append("Content2")
}
}
}
}
}
 
J

Jim Weirich

Miles said:
I would like to use Ruby and REXML to wrap an XML document and allow
access to the element nodes, attributes, and text. Essentially I need
an XML document builder loosely coupled from the document.

It seems like Ruby is powerful enough to code generate a class given an
XML document or build an object at run-time with the appropriate
accessors.

For instance:

order = XmlBuilder.new
[... example elided ...]

Are you wanting to build a DOM object, or build a string containing XML
markup? If the later, Builder::XmlMarkup will do this. If the former,
it would be interesting to create a Builder with a similar API to
Buidler::XmlMarkup, but generated DOM trees instead of strings.

Or perhaps you are looking for something completely different.

XML Builder Link: http://builder.rubyforge.org/
 
S

Simon Kröger

Hi Miles,

interesting idea, i did a quick (proof of concept) hack:
-------------------------------------------------------------
class Xmltree
attr_accessor :childs
attr_accessor :content
attr_accessor :attributes

def initialize
self.childs = []
self.attributes = {};
end

def method_missing meth, *args, &block
return attributes[args[0]] = args[1] if meth == :[]=
return attributes[args[0]] if meth == :[]
return self.content = args if meth == '='.intern

unless child = childs.assoc(meth.to_s.chomp('='))
childs << child = [meth.to_s.chomp('='), Xmltree.new]
end

return child[1] if meth.to_s[-1] != ?=
child[1].content = args
end

def to_s
childs.map do |t, c|
"""<#{t} #{c.attributes.map do |a, v|
"#{a}=\"#{v}\""
end.join(' ')}>\n#{c}</#{t}>\n"""
end.join + content.to_s + (content ? "\n" : '')
end
end
-------------------------------------------------------------

usage:
-------------------------------------------------------------
xml = Xmltree.new

xml.header.title = 'this is a demo'
xml.body.component['type'] = 'the answer'
xml.body.component = 42

puts xml
-------------------------------------------------------------

output:
-------------------------------------------------------------
<header >
<title >
this is a demo
</title>
</header>
<body >
<component type="the answer">
42
</component>
</body>
-------------------------------------------------------------

cheers

Simon

Miles Monroe:
 
M

Miles Monroe

Simon said:
Hi Miles,

interesting idea, i did a quick (proof of concept) hack:
-------------------------------------------------------------
class Xmltree
attr_accessor :childs
attr_accessor :content
attr_accessor :attributes

def initialize
self.childs = []
self.attributes = {};
end

def method_missing meth, *args, &block
return attributes[args[0]] = args[1] if meth == :[]=
return attributes[args[0]] if meth == :[]
return self.content = args if meth == '='.intern

unless child = childs.assoc(meth.to_s.chomp('='))
childs << child = [meth.to_s.chomp('='), Xmltree.new]
end

return child[1] if meth.to_s[-1] != ?=
child[1].content = args
end

def to_s
childs.map do |t, c|
"""<#{t} #{c.attributes.map do |a, v|
"#{a}=\"#{v}\""
end.join(' ')}>\n#{c}</#{t}>\n"""
end.join + content.to_s + (content ? "\n" : '')
end
end
-------------------------------------------------------------

usage:
-------------------------------------------------------------
xml = Xmltree.new

xml.header.title = 'this is a demo'
xml.body.component['type'] = 'the answer'
xml.body.component = 42

puts xml
-------------------------------------------------------------

output:
-------------------------------------------------------------
<header >
<title >
this is a demo
</title>
</header>
<body >
<component type="the answer">
42
</component>
</body>
-------------------------------------------------------------

cheers

Simon

Miles Monroe:


Awesome! That is better than I ever imagined.

Back in my Perl days, I started creating a source filter to allow the
insertion of non-Perl XPath statements that worked on an implicit XML
document.

I used the source filter to first scan the code for naked XPath
statements and then built the XML document with the slightly-modified
XPath syntax. I converted the invalid non-Perl strings into valid Perl
in the source filter.

Likewise, is it possible to insert non-Ruby text in the main namespace
and then turn it into Ruby code before the rest of the script is parsed?
I guess I'm asking if it's possible to implement a source filter in
Ruby.

Thanks.
 
B

Benjohn Barnes

Last time I was doing playing with XML, I wanted to be able to,
basically, add methods on to the nodes matching xpaths. It didn't
seem to be very easy. I wondered at the time if some kind of
transform idea would work better.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
474,202
Messages
2,571,057
Members
47,667
Latest member
DaniloB294

Latest Threads

Top