[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.ruby

xml in Ruby

paul vudmaska

10/2/2003 2:28:00 PM

The biggest problem i have with Ruby is the sleepness
nights.... ;->

Has anyone heard of e4x...emcascript(aka javascript)
for xml?

http://dev2dev.bea.com/products/wlworkshop/articles/JSchneid...

Basically it is an attempt to roll xml as a native
type into ecmascript. I'd suggest Ruby could benefit
and set itself apart by doing so. Following is my own
quick and dirty Ruby'd version of the above.(you might
want to check it out first)

# xml literal...
p = %x{<Peeps><P>paul</P><P>john</P><P/></Peeps>}
or
p <<<XML
<Peeps>
<P>paul</P>
<P>john</P>
<P/>
</Peeps>
XML
#access
mary = p.Peeps.P[3]#xpath starts with 1...

#edit
mary = 'mary'#convenience method appending text to P
element
#add element
p.Peeps << %x{<P>Ringo</P>}

#iter.
p.Peeps.each('P') do |person|

puts person #>paul,john,mary,ringo

end

Instead of the dot notation for swiching context
suggested in the above article, perhaps use xpath
exclusively,imo.

p.each('//P') do ...end

So, basically, rexml rolled into ruby natively.

But what about the much maligned xsl stylesheets? We
need style too - Rubystyle!

# prob a million ways to do this...
style = <<<STYLE
<div>
<h1>#{P}</h1> is a rock star
</div>
STYLE
...here's one
output = p.each('//P').transform(style)


There's plenty of room for rolling more
organic/programic/rubylike approaches to style than
xsl into Ruby(particulary considering Ruby's iters and
blocks). I'm not sure this is the wisest approach, and
think people like Michael Kay(an xsl guru) might point
out the folly of this. And keeping to a standard would
be good for a product such as Ruby but it sure is
intersting...at least to me.

So now we've
1) done what javascript might be doing but totally
trumped them with (ruby)style.
2) added a feature that python and perl can only wish
for
3) created an internal common data structure that is
similar to the array, hash and struct but is sometimes
better and certainly more portable/readable.
4) now a native type, we can import/export data to
whatever speaks xml without worrying about
implementation.
5) have an inherent mechanism for seperating duties
<important>within code</important>- ie data from style
6)a powerful native templating system. Great for web
stuff particularily. Picture putting the power of ruby
in templates that are sandboxed. No need to learn
template language X. Do it in ruby or subset of.
6+) prob much more, xml tends to feed upon itself

Whatcha think? Can i count on this by 1.8.1? ;->

:pv

PS:as for the previous comment at artima about the
limitations of Ruby - stone that guy! :) Not really-
seemed like legit points 2me. I want Ruby to scale to
1 mil hits per sec on my ipaq too - but not at the
expense of creativity, malability, fidelity,
pragmatism or effectiveness.


__________________________________
Do you Yahoo!?
The New Yahoo! Shopping - with improved product search
http://shopping...

1 Answer

Erik Terpstra

10/2/2003 3:20:00 PM

0

Last year I made a quick hack that could do something like that.
I didn't have much experience with Ruby back then, so it is a quick and
very dirty solution. But the following works:


require 'XML'

y = XML %{
<employees>
<employee>
<name>Joe</name>
<age>28</age>
<department>
<name>Engineering</name>
</department>
</employee>
<employee>
<name>Ken</name>
<age>26</age>
<department>
<name>Engineering</name>
</department>
</employee>
</employees>
}

puts y.employees.employee[0].age
y.employees.employee[0].age = '9'
puts y.employees.employee[0].age

y.employees.employee.each do |employee|
puts "name: #{employee.name}, age: #{employee.age}"
end



doc = XML %{
<order>
<customer>
<name>I. Wannabuy</name>
<address>
<street>53 Party Lane</street>
<city>Anywhere</city>
<state>CA</state>
<zip>12345</zip>
</address>
</customer>
<item>
<description>Large Purple Dinosaur,
Generic</description>
<quantity>35</quantity>
<price>24.99</price>
</item>
<item>
<description>Catapult</description>
<quantity>1</quantity>
<price>149.95</price>
</item>
<item>
<description>300 foot measuring tape</description>
<quantity>1</quantity>
<price>9.95</price>
</item>
</order>
}

def calc_total(order)
total = 0
order.item.each do |item|
total += item.price.to_f * item.quantity.to_i
end
return total
end

puts "total: #{calc_total(doc.order)}"












======================================================

This is the file XML.rb that makes it work:

======================================================


require 'xmltreebuilder'
require 'perlvalue'

ELEMENT_NODE = 1; ATTRIBUTE_NODE = 2; TEXT_NODE = 3

module Kernel
def XML(xml)
RNX.new(xml)
end
end

class RNX
def initialize(xml)
@level = 0; @line = @source = ''; @path = []
builder = XML::DOM::Builder.new
begin
dom = builder.parse xml.gsub(/\s+/, '')
rescue
puts "#{$0}: #{$!} (in line #{builder.line}";
exit 1
end
dom.documentElement.normalize
traverse dom
eval %{
@#{dom.documentElement.nodeName} = PerlValue.new
#{@source}

def self.#{dom.documentElement.nodeName}
return @#{dom.documentElement.nodeName}
end
}
end

def traverse(node)
index = 0
node.childNodes.each do |n|
if n.nodeType == ELEMENT_NODE
@path[@level] = n.nodeName
if (n.nextSibling and
n.nextSibling.nodeName == n.nodeName) or (n.previousSibling and
n.previousSibling.nodeName == n.nodeName)
@path[@level] += "[#{index}]"
index += 1
end
@line = @path.join('.')
@level += 1; traverse n; @level -= 1
@path.delete_at(@level)
elsif n.nodeType == TEXT_NODE
@line += " = '#{n.data}'\n" if n.data
=~ /\S/ #optional!!!
@source += "@#{@line}"
end
end
end
end