Does anybody know of a library that allows to go through an xml tree as if
it were made of normal objects?
I have seen e4x on rubyforge, but it doesn't seem to work. simplexml returns
hashes rather than employing dynamic method calls
What I need to do is to be able to traverse an xml document as in:
* people.each_person {...}
* people.person[2].name
* people.person.name #takes the first person
* people.person.size
etc..
Any suggestion?
--kia
HAL_9000
(HAL 9000)
31 July 2006 13:30
#2
chiaro scuro wrote:
Does anybody know of a library that allows to go through an xml tree as if
it were made of normal objects?
I have seen e4x on rubyforge, but it doesn't seem to work. simplexml returns
hashes rather than employing dynamic method calls
What I need to do is to be able to traverse an xml document as in:
* people.each_person {...}
* people.person[2].name
* people.person.name #takes the first person
* people.person.size
etc..
Any suggestion?
I like the idea, but I'm unaware that it's been done
to that level.
Why don't you start with REXML and put a wrapper on it?
Then publish it for everyone to enjoy.
Or do you find REXML too slow for your use?
Hal
My xmlcodec project will do this but you'll need to write some simple
classes to do it. For this case, something like:
class PeopleFormat < XMLElement
xmlformat 'People Format'
end
class People < PeopleFormat
elname :people
xmlsubel_mult :person
end
class Person < PeopleFormat
elname :person
xmlattr :name
xmlattr :size
end
With this you can do:
people = PeopleFormat.import_xml_text(myXMLTextOrFile)
people.person.each {|p| ...}
people.person.first.name
people.person[2].type
You can find it at http://xmlcodec.rubyforge.org
Cheers,
Pedro.
···
On 7/31/06, chiaro scuro <kiaroskuro@gmail.com > wrote:
Does anybody know of a library that allows to go through an xml tree as if
it were made of normal objects?
I have seen e4x on rubyforge, but it doesn't seem to work. simplexml returns
hashes rather than employing dynamic method calls
What I need to do is to be able to traverse an xml document as in:
* people.each_person {...}
* people.person[2].name
* people.person.name #takes the first person
* people.person.size
Look here:
<http://code.whytheluckystiff.net/hpricot/ >
or here:
<http://cvs.m17n.org/~akr/htree/ >
···
On Jul 31, 2006, at 6:16 AM, chiaro scuro wrote:
Does anybody know of a library that allows to go through an xml tree as if
it were made of normal objects?
I have seen e4x on rubyforge, but it doesn't seem to work. simplexml returns
hashes rather than employing dynamic method calls
What I need to do is to be able to traverse an xml document as in:
* people.each_person {...}
* people.person[2].name
* people.person.name #takes the first person
* people.person.size
etc..
Any suggestion?
--
And those who were seen dancing were thought to be insane by those who could not hear the music.
-Friedrich Wilhelm Nietzsche, philosopher (1844-1900)
Hi,
chiaro scuro wrote:
Does anybody know of a library that allows to go through an xml tree as if
it were made of normal objects?
What I need to do is to be able to traverse an xml document as in:
* people.each_person {...}
* people.person[2].name
* people.person.name #takes the first person
* people.person.size
0% cat people.xml
<people>
<person>
<name>name1</name>
<size>1</size>
</person>
<person>
<name>name2</name>
<size>2</size>
</person>
<person>
<name>name3</name>
<size>3</size>
</person>
</people>
0% irb
irb(main):001:0> require 'xsd/mapping'
=> true
irb(main):002:0> people = XSD::Mapping.xml2obj(File.read("people.xml"))
=> #<SOAP::Mapping::Object:0x3592020
{}person=[#<SOAP::Mapping::Object:0x3591ea0 {}name="name1" {}size="1">,
#<SOAP::Mapping::Object:0x3591684 {}name="name2" {}size="2">,
#<SOAP::Mapping::Object:0x3590f7c {}name="name3" {}size="3">]>
irb(main):003:0> people.person.each { |person| p person }
#<SOAP::Mapping::Object:0x3591ea0 {}name="name1" {}size="1">
#<SOAP::Mapping::Object:0x3591684 {}name="name2" {}size="2">
#<SOAP::Mapping::Object:0x3590f7c {}name="name3" {}size="3">
=> [#<SOAP::Mapping::Object:0x3591ea0 {}name="name1" {}size="1">,
#<SOAP::Mapping::Object:0x3591684 {}name="name2" {}size="2">,
#<SOAP::Mapping::Object:0x3590f7c {}name="name3" {}size="3">]
irb(main):004:0> people.person[2].name
=> "name3"
irb(main):005:0> people.person.name
NoMethodError: undefined method `name' for #<Array:0x6b22108>
from (irb):5
irb(main):006:0>
Almost.
Regards,
// NaHi
Tim_Bray
(Tim Bray)
31 July 2006 15:16
#6
Consider
<vocab-item>
<first.form>foo</first.form>
<second.form>föö</second.form>
</vocab-item>
That's legal XML. Ruby n00b question: can you work around problems like "vocab-item" and "first.form" in Ruby? -Tim
···
On Jul 31, 2006, at 6:16 AM, chiaro scuro wrote:
What I need to do is to be able to traverse an xml document as in:
* people.each_person {...}
* people.person[2].name
* people.person.name #takes the first person
* people.person.size
Does anybody know of a library that allows to go through an xml tree as if
it were made of normal objects?
Your sample code looks a lot like RubyfulSoup. Although originally intended for traversing HTML documents, it has an option for non-specific XML as well.
* people.each_person {...}
* people.person[2].name
* people.person.name #takes the first person
* people.person.size
RubyfulSoup would (I believe) look something like:
people.find_all['person'].each
people.person.name
people.person.size
if the XML were like
<people>
<person>
<name>Fred</name>
<size>150 kg</size>
</person>
<person>
<name>Sally</name>
.
</person>
</people>
If instead your XML is like
<people>
<person name="Fred" size="150 kg"/>
<person name="Sally" size="88 kg"/>
.
</people>
Then you'd be looking at
people.find_all['person'].each
people.person['name']
people.person['size']
I don't remember what it does with XML tags with squiggles and dots.
···
On Jul 31, 2006, at 6:16, chiaro scuro wrote:
I'm experimenting with this XML2RB [1]. The idea is to generate
a DSL for a class of XML files (from a bunch of XML files).
Each XML file in this class can be translated to a Ruby script,
which can be executed with the DSL. Running a script actually
builds the tree by default, including the classes and methods
as you mentioned. Each class can optionally be enriched with
new functionality.
All examples are real, but I've not yet released any code.
Untill now, it's just an experiment.
The document will grow every now and then. It's not static.
gegroet,
Erik V. - http://www.erikveen.dds.nl/
[1] http://www.erikveen.dds.nl/xml2rb/index.html
That's really nice, I'd looked over that in the standard library. I've used
Roxml with success to achieve the same effect, but it requires more work.
Alex
···
On Monday 31 July 2006 14:43, NAKAMURA, Hiroshi wrote:
0% irb
irb(main):001:0> require 'xsd/mapping'
=> true
irb(main):002:0> people = XSD::Mapping.xml2obj(File.read("people.xml"))
=> #<SOAP::Mapping::Object:0x3592020
{}person=[#<SOAP::Mapping::Object:0x3591ea0 {}name="name1" {}size="1">,
#<SOAP::Mapping::Object:0x3591684 {}name="name2" {}size="2">,
#<SOAP::Mapping::Object:0x3590f7c {}name="name3" {}size="3">]>
irb(main):003:0> people.person.each { |person| p person }
#<SOAP::Mapping::Object:0x3591ea0 {}name="name1" {}size="1">
#<SOAP::Mapping::Object:0x3591684 {}name="name2" {}size="2">
#<SOAP::Mapping::Object:0x3590f7c {}name="name3" {}size="3">
=> [#<SOAP::Mapping::Object:0x3591ea0 {}name="name1" {}size="1">,
#<SOAP::Mapping::Object:0x3591684 {}name="name2" {}size="2">,
#<SOAP::Mapping::Object:0x3590f7c {}name="name3" {}size="3">]
irb(main):004:0> people.person[2].name
=> "name3"
irb(main):005:0> people.person.name
NoMethodError: undefined method `name' for #<Array:0x6b22108>
from (irb):5
irb(main):006:0>
Almost.
Regards,
// NaHi
uhm.. I admit I didn't think of that. I guess I will have to write some
kind of name normalized/denormalizer taking care of dots and hyphens.
all hyphens and dots will become underscores, I guess, and I'll just assume
nobody will try to get the code to fail using both at the same time
nobody will, right?
···
On 7/31/06, Tim Bray <tbray@textuality.com > wrote:
On Jul 31, 2006, at 6:16 AM, chiaro scuro wrote:
> What I need to do is to be able to traverse an xml document as in:
>
> * people.each_person {...}
> * people.person[2].name
> * people.person.name #takes the first person
> * people.person.size
Consider
<vocab-item>
<first.form>foo</first.form>
<second.form>föö</second.form>
</vocab-item>
That's legal XML. Ruby n00b question: can you work around problems
like "vocab-item" and "first.form" in Ruby? -Tim
--
Chiaroscuro
---
Liquid Development: http://liquiddevelopment.blogspot.com/
class Foo
define_method("first.form") do
"hi from first.form"
end
end
Foo.new.send("first.form") # => "hi from first.form"
-- Daniel
···
On Jul 31, 2006, at 11:16 AM, Tim Bray wrote:
Consider
<vocab-item>
<first.form>foo</first.form>
<second.form>föö</second.form>
</vocab-item>
That's legal XML. Ruby n00b question: can you work around problems like "vocab-item" and "first.form" in Ruby?
Workaround is the word <g>
class A
define_method("@+$%!") { puts "Snoopy talk!" }
end
a = A.new
a.send("@+$%!")
···
On Jul 31, 2006, at 11:16 AM, Tim Bray wrote:
On Jul 31, 2006, at 6:16 AM, chiaro scuro wrote:
What I need to do is to be able to traverse an xml document as in:
* people.each_person {...}
* people.person[2].name
* people.person.name #takes the first person
* people.person.size
Consider
<vocab-item>
<first.form>foo</first.form>
<second.form>föö</second.form>
</vocab-item>
That's legal XML. Ruby n00b question: can you work around problems like "vocab-item" and "first.form" in Ruby? -Tim
Tim Bray <tbray@textuality.com > writes:
···
On Jul 31, 2006, at 6:16 AM, chiaro scuro wrote:
What I need to do is to be able to traverse an xml document as in:
* people.each_person {...}
* people.person[2].name
* people.person.name #takes the first person
* people.person.size
Consider
<vocab-item>
<first.form>foo</first.form>
<second.form>föö</second.form>
</vocab-item>
That's legal XML. Ruby n00b question: can you work around problems
like "vocab-item" and "first.form" in Ruby? -Tim
Just make the API more flexible:
document["vocab-item"].bla["second.form"]
--
Christian Neukirchen <chneukirchen@gmail.com > http://chneukirchen.org
Hi,
Tim Bray wrote:
Consider
<vocab-item>
<first.form>foo</first.form>
<second.form>föö</second.form>
</vocab-item>
That's legal XML. Ruby n00b question: can you work around problems like
"vocab-item" and "first.form" in Ruby? -Tim
With xsd/mapping;
0% irb
irb(main):001:0> require 'xsd/mapping'
=> true
irb(main):002:0> obj = XSD::Mapping.xml2obj(<<XML)
irb(main):003:1" <obj>
irb(main):004:1" <vocab-item>
irb(main):005:1" <first.form>foo</first.form>
irb(main):006:1" <second.form>foo</second.form>
irb(main):007:1" </vocab-item>
irb(main):008:1" </obj>
irb(main):009:1" XML
=> #<SOAP::Mapping::Object:0x3591144
{}vocab-item=#<SOAP::Mapping::Object:0x3590f64 {}first.form="foo"
{}second.form="foo">>
irb(main):010:0> obj.methods - Kernel.methods
=> ["[]", "vocab_item=", "[]=", "__xmlattr", "__xmlele",
"__add_xmlele_value", "vocab_item"]
irb(main):011:0> obj["vocab-item"]
=> #<SOAP::Mapping::Object:0x3590f64 {}first.form="foo" {}second.form="foo">
irb(main):012:0> obj[XSD::QName.new(nil, "vocab-item")]
=> #<SOAP::Mapping::Object:0x3590f64 {}first.form="foo" {}second.form="foo">
Last line is for your next question, XML Namespace. And see "__xmlattr"
method listed for the next.
Regards,
// NaHi
Ptkwt
31 July 2006 22:30
#15
In article <62e8012c0607310632hb44a0b6md149d6462d20130c@mail.gmail.com >,
···
Pedro Côrte-Real <pedro@pedrocr.net > wrote:
On 7/31/06, chiaro scuro <kiaroskuro@gmail.com > wrote:
Does anybody know of a library that allows to go through an xml tree as if
it were made of normal objects?
I have seen e4x on rubyforge, but it doesn't seem to work. simplexml returns
hashes rather than employing dynamic method calls
What I need to do is to be able to traverse an xml document as in:
* people.each_person {...}
* people.person[2].name
* people.person.name #takes the first person
* people.person.size
My xmlcodec project will do this but you'll need to write some simple
classes to do it. For this case, something like:
class PeopleFormat < XMLElement
xmlformat 'People Format'
end
class People < PeopleFormat
elname :people
xmlsubel_mult :person
end
class Person < PeopleFormat
elname :person
xmlattr :name
xmlattr :size
end
With this you can do:
people = PeopleFormat.import_xml_text(myXMLTextOrFile)
people.person.each {|p| ...}
people.person.first.name
people.person[2].type
You can find it at http://xmlcodec.rubyforge.org
Nice. I've done this sort of thing, but much more 'manually' than you
show here.
Phil
Hi,
What I need to do is to be able to traverse an xml document as in:
* people.each_person {...}
* people.person[2].name
* people.person.name #takes the first person
* people.person.size
Consider
<vocab-item>
<first.form>foo</first.form>
<second.form>föö</second.form>
</vocab-item>
That's legal XML. Ruby n00b question: can you work around problems like "vocab-item" and "first.form" in Ruby? -Tim
I feel *compelled* to mention xampl (<http://rubyforge.org/projects/xampl/ >). Using the current version for ruby, the program looks like this:
thing = open("xml/funnystuff.xml"){ | f | XamplObject.from_xml_string f.read }
puts thing.pp_xml
puts thing.class.name
thing.first_form.first.content = 'hello there'
puts thing.pp_xml
The output like this:
<vocab-item>
<first.form>foo</first.form>
<second.form>föö</second.form></vocab-item>
XamplAdHoc::VocabItem
<vocab-item>
<first.form>hello there</first.form>
<second.form>föö</second.form></vocab-item>
The file xml/funnystuff.xml has Tim's example xml in it.
The XamplAdHoc stuff is there because there is no namespace declarations in the xml and I didn't supply a default mapping to a Ruby Module.
Xampl does a lot more than this (in particular it does a weak-transactional 'transparent' persistence kind of thing). It has been around in Java since the late 1990s (where it does 'real' transactions', CommonLisp for a couple of years, and Ruby for 18 months. I've written several programs well over 500 kloc using the Java version. Currently using xampl in place of ActiveRecord in a Rails project I'm working on (but you need the version I'm preparing to release for use with Rails, so please be patient).
Cheers,
Bob
···
On Jul 31, 2006, at 11:16 AM, Tim Bray wrote:
On Jul 31, 2006, at 6:16 AM, chiaro scuro wrote:
----
Bob Hutchison -- blogs at <http://www.recursive.ca/hutch/ >
Recursive Design Inc. -- <http://www.recursive.ca/ >
Raconteur -- <http://www.raconteur.info/ >
xampl for Ruby -- <http://rubyforge.org/projects/xampl/ >
Hi,
0% cat people.xml
<people>
<person>
<name>name1</name>
<size>1</size>
</person>
<person>
<name>name2</name>
<size>2</size>
</person>
<person>
<name>name3</name>
<size>3</size>
</person>
</people>
0% irb
irb(main):001:0> require 'xsd/mapping'
=> true
irb(main):002:0> people = XSD::Mapping.xml2obj(File.read("people.xml"))
=> #<SOAP::Mapping::Object:0x3592020
{}person=[#<SOAP::Mapping::Object:0x3591ea0 {}name="name1" {}size="1">,
#<SOAP::Mapping::Object:0x3591684 {}name="name2" {}size="2">,
#<SOAP::Mapping::Object:0x3590f7c {}name="name3" {}size="3">]>
irb(main):003:0> people.person.each { |person| p person }
#<SOAP::Mapping::Object:0x3591ea0 {}name="name1" {}size="1">
#<SOAP::Mapping::Object:0x3591684 {}name="name2" {}size="2">
#<SOAP::Mapping::Object:0x3590f7c {}name="name3" {}size="3">
=> [#<SOAP::Mapping::Object:0x3591ea0 {}name="name1" {}size="1">,
#<SOAP::Mapping::Object:0x3591684 {}name="name2" {}size="2">,
#<SOAP::Mapping::Object:0x3590f7c {}name="name3" {}size="3">]
irb(main):004:0> people.person[2].name
=> "name3"
irb(main):005:0> people.person.name
NoMethodError: undefined method `name' for #<Array:0x6b22108>
from (irb):5
irb(main):006:0>
Almost.
Nice! I didn't know about this.
Loses child ordering though, mixed content, and the root element?
Both of the following lines:
puts XSD::Mapping.obj2xml(XSD::Mapping.xml2obj("<p><a/><b/><a/><b/></
"))
puts XSD::Mapping.obj2xml(XSD::Mapping.xml2obj("<p>1<a/>2<b/>3<a/>4<b/ >5</p>"))
give the same output:
<?xml version="1.0" encoding="utf-8" ?>
<SOAP..Mapping..Object>
<a>
</a>
<a>
</a>
<b>
</b>
<b>
</b>
</SOAP..Mapping..Object>
Cheers,
Bob
···
On Jul 31, 2006, at 9:43 AM, NAKAMURA, Hiroshi wrote:
----
Bob Hutchison -- blogs at <http://www.recursive.ca/hutch/ >
Recursive Design Inc. -- <http://www.recursive.ca/ >
Raconteur -- <http://www.raconteur.info/ >
xampl for Ruby -- <http://rubyforge.org/projects/xampl/ >
7rans
(7rans)
8 August 2006 13:15
#18
chiaro scuro wrote:
> Does anybody know of a library that allows to go through an xml tree as if
> it were made of normal objects?
>
> I have seen e4x on rubyforge, but it doesn't seem to work. simplexml
> returns
> hashes rather than employing dynamic method calls
>
> What I need to do is to be able to traverse an xml document as in:
>
> * people.each_person {...}
> * people.person[2].name
> * people.person.name #takes the first person
> * people.person.size
>
> etc..
>
> Any suggestion?
It's not really the best way to traverse XML becuase there's some
exceptions --keywords that ruby uses that wouldn't be traverable as
tags, and legal XML tags that you would not be able to use as method
calls.
I'm suprised the the e4x implemention on Rubyforge didn't work at all
--I'll have to look at it, but in any case it is completely
expiremental, and incomplete. For my needs I have moved on to a
Ruby-esque interface instead (http://cherry.rubyforge.org ).
T.
in the meantime I wrote a little REXML wrapper, but I'll check the solutions
you guys sent me and see if I can throw away some code
cheers,
Kia
Hi,
Bob Hutchison wrote:
Loses child ordering though, mixed content, and the root element?
Yes, Yes and Yes. obj2xml and xml2obj is not for round-trip conversion
although its name indicates it.
I introduced this XML <-> Ruby mapping to avoid bothersome XML DOM
programming in Web Services (soap4r). Do you think xampl can help us
instead of XSD::Mapping?
For example, flickr client is as follows;
(cf. http://dev.ctor.org/soap4r/browser/trunk/sample/soap/flickr.rb )
flickr = SOAP::RPC::Driver.new('http://www.flickr.com/services/soap/ ')
...
response = flickr.request(
:api_key => api_key,
:method => 'flickr.test.echo',
:name => 'hello world')
responsexml = "<dummy>#{response}</dummy>" # svr returns partial XML!
require 'xsd/mapping'
obj = XSD::Mapping.xml2obj(responsexml)
p obj.method
p obj.name
Creating XML request with a Hash and creating Ruby object with
XSD::Mapping. Both are for XML <-> Ruby mapping. It's enough small but
when I come to create more complexed XML instance... How I can write
this with xampl?
Regards,
// NaHi