Ben Hall
2009-Jan-01 17:48 UTC
[Ironruby-core] Xml Processing in IronRuby - Help me improve the wrapper
Hello,
I''ve just been playing around with IronRuby and processing some XML
from a REST service. I''ve created this wrapper:
require ''mscorlib''
require ''System, Version=2.0.0.0, Culture=neutral,
PublicKeyToken=b77a5c561934e089''
include System
require ''System.Xml, Version=2.0.0.0, Culture=neutral,
PublicKeyToken=b77a5c561934e089''
include System::Xml
#Wrapper around .Net XMLDocument to make it easier to query with -
more like REXML
class Document
def initialize(xml)
@document = XmlDocument.new
@document.load_xml xml
end
def get(xpath) #.collect - I want to pass the block in, not have
to use it on the outside.
@document.SelectNodes(xpath)
end
end
class XmlNodeList
def get(name)
list.select {|e| e.Name == name}
end
end
class XmlElement
def get(name)
if has_attribute name
get_attribute name
else
get_elements_by_tag_name name
end
end
def text
inner_text
end
end
My first problem is that I''m getting XmlElement object instead of
XmlNode from an XmlNodeList. If I had XmlNode, then I could do
e[''n''].text - which is what I want. As a result, my code to
access
the N element looks like this:
require ''xml''
@document =
Document.new(''<x><x1><n>test</n><z>aaa</z></x1></x>'')
@document.get(''x'').collect {|n| puts
n.text}>> testaaa
>>> @document.get(''x/x1'').collect {|e|
e.get(''n'').collect {|n| puts n.text}}
test
Why am I getting a XmlElement object? How can I access my xml in a
cleaner fashion?
My second problem, I wanted to be able to pass in a block
def get(xpath)
@document.SelectNodes(xpath).collect {yield}
end
In this case, I get the following error:>>> @document.get(''x'') {|n| puts n.text}
:1: undefined method `text'' for nil:NilClass (NoMethodError)
from xml.rb:27:in `get''
I changed it to {|n| yield}, but I get the same error. The object is
always nil. What am I doing wrong?
Hope this all makes sense.
Thanks
Ben
Ivan Porto Carrero
2009-Jan-01 18:01 UTC
[Ironruby-core] Xml Processing in IronRuby - Help me improve the wrapper
I wrote something similar a while ago
http://github.com/casualjim/ironnails/tree/master/IronNails/vendor/iron_nails/lib/iron_xml.rb
statuses = []
IronXml.parse(''friends_timeline.xml'', :document) do |doc|
doc.elements(''statuses'') do |status|
st = Status.new
st.id = status.element(''id'').value
st.created_at = status.element(''created_at'').value
st.text = status.element(''text'').value
st.source = status.element(''source'').value
st.truncated = status.element(''truncated'').value
st.in_reply_to_status_id =
status.element(''in_reply_to_status_id'').value
st.in_reply_to_user_id =
status.element(''in_reply_to_user_id'').value
st.favorited = status.element(''favorited'').value
status.elements(''user'') do |user|
# process user here
end
statuses << st
end
end
or
statuses = []
IronXml.parse(''friends_timeline.xml'', :document) do |doc|
doc.statuses do |status|
st = Status.new
st.id = status.id
st.created_at = status.created_at
st.text = status.text
st.source = status.source
st.truncated = status.truncated
st.in_reply_to_status_id = status.in_reply_to_status_id
st.in_reply_to_user_id = status.in_reply_to_user_id
st.favorited = status.favorited
status.user do |user|
# process user here
end
statuses << st
end
end
You can maybe look there for inspiration :)
On Thu, Jan 1, 2009 at 6:48 PM, Ben Hall <ben2004uk at googlemail.com>
wrote:
> Hello,
>
> I''ve just been playing around with IronRuby and processing some
XML
> from a REST service. I''ve created this wrapper:
> require ''mscorlib''
> require ''System, Version=2.0.0.0, Culture=neutral,
> PublicKeyToken=b77a5c561934e089''
> include System
> require ''System.Xml, Version=2.0.0.0, Culture=neutral,
> PublicKeyToken=b77a5c561934e089''
> include System::Xml
>
> #Wrapper around .Net XMLDocument to make it easier to query with -
> more like REXML
> class Document
> def initialize(xml)
> @document = XmlDocument.new
> @document.load_xml xml
> end
>
> def get(xpath) #.collect - I want to pass the block in, not have
> to use it on the outside.
> @document.SelectNodes(xpath)
> end
> end
>
> class XmlNodeList
> def get(name)
> list.select {|e| e.Name == name}
> end
> end
>
> class XmlElement
> def get(name)
> if has_attribute name
> get_attribute name
> else
> get_elements_by_tag_name name
> end
> end
>
> def text
> inner_text
> end
> end
>
> My first problem is that I''m getting XmlElement object instead of
> XmlNode from an XmlNodeList. If I had XmlNode, then I could do
> e[''n''].text - which is what I want. As a result, my code
to access
> the N element looks like this:
>
> require ''xml''
> @document =
Document.new(''<x><x1><n>test</n><z>aaa</z></x1></x>'')
> @document.get(''x'').collect {|n| puts n.text}
> >> testaaa
>
> >>> @document.get(''x/x1'').collect {|e|
e.get(''n'').collect {|n| puts
> n.text}}
> test
>
> Why am I getting a XmlElement object? How can I access my xml in a
> cleaner fashion?
>
>
> My second problem, I wanted to be able to pass in a block
>
> def get(xpath)
> @document.SelectNodes(xpath).collect {yield}
> end
>
> In this case, I get the following error:
> >>> @document.get(''x'') {|n| puts n.text}
> :1: undefined method `text'' for nil:NilClass (NoMethodError)
> from xml.rb:27:in `get''
>
> I changed it to {|n| yield}, but I get the same error. The object is
> always nil. What am I doing wrong?
>
> Hope this all makes sense.
>
> Thanks
>
> Ben
> _______________________________________________
> Ironruby-core mailing list
> Ironruby-core at rubyforge.org
> http://rubyforge.org/mailman/listinfo/ironruby-core
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL:
<http://rubyforge.org/pipermail/ironruby-core/attachments/20090101/e1f92717/attachment-0001.html>
Ben Hall
2009-Jan-01 18:35 UTC
[Ironruby-core] Xml Processing in IronRuby - Help me improve the wrapper
Excellent!! Thank you. I was missing select_single_node and &b ;)
Wrapper is now sorted, and I can do:
require ''xml''
@document =
Document.new(''<x><x1><z>test</z><y><q>abc</q></y></x1><x1><z>tester</z><a>testeraaa</a></x1></x>'')
@document.elements(''x/x1'') do |e|
puts e.get(''z'')
e.node(''y'') {|y| puts y.get(''q'')}
end
Thanks
Ben
On Thu, Jan 1, 2009 at 6:01 PM, Ivan Porto Carrero <ivan at
flanders.co.nz> wrote:> I wrote something similar a while ago
>
>
http://github.com/casualjim/ironnails/tree/master/IronNails/vendor/iron_nails/lib/iron_xml.rb
>
> statuses = []
> IronXml.parse(''friends_timeline.xml'', :document) do |doc|
> doc.elements(''statuses'') do |status|
> st = Status.new
> st.id = status.element(''id'').value
> st.created_at = status.element(''created_at'').value
> st.text = status.element(''text'').value
> st.source = status.element(''source'').value
> st.truncated = status.element(''truncated'').value
> st.in_reply_to_status_id =
status.element(''in_reply_to_status_id'').value
> st.in_reply_to_user_id =
status.element(''in_reply_to_user_id'').value
> st.favorited = status.element(''favorited'').value
> status.elements(''user'') do |user|
> # process user here
> end
>
> statuses << st
> end
> end
>
> or
>
> statuses = []
> IronXml.parse(''friends_timeline.xml'', :document) do |doc|
> doc.statuses do |status|
> st = Status.new
> st.id = status.id
> st.created_at = status.created_at
> st.text = status.text
> st.source = status.source
> st.truncated = status.truncated
> st.in_reply_to_status_id = status.in_reply_to_status_id
> st.in_reply_to_user_id = status.in_reply_to_user_id
> st.favorited = status.favorited
> status.user do |user|
> # process user here
> end
>
> statuses << st
> end
> end
>
>
> You can maybe look there for inspiration :)
>
> On Thu, Jan 1, 2009 at 6:48 PM, Ben Hall <ben2004uk at
googlemail.com> wrote:
>>
>> Hello,
>>
>> I''ve just been playing around with IronRuby and processing
some XML
>> from a REST service. I''ve created this wrapper:
>> require ''mscorlib''
>> require ''System, Version=2.0.0.0, Culture=neutral,
>> PublicKeyToken=b77a5c561934e089''
>> include System
>> require ''System.Xml, Version=2.0.0.0, Culture=neutral,
>> PublicKeyToken=b77a5c561934e089''
>> include System::Xml
>>
>> #Wrapper around .Net XMLDocument to make it easier to query with -
>> more like REXML
>> class Document
>> def initialize(xml)
>> @document = XmlDocument.new
>> @document.load_xml xml
>> end
>>
>> def get(xpath) #.collect - I want to pass the block in, not have
>> to use it on the outside.
>> @document.SelectNodes(xpath)
>> end
>> end
>>
>> class XmlNodeList
>> def get(name)
>> list.select {|e| e.Name == name}
>> end
>> end
>>
>> class XmlElement
>> def get(name)
>> if has_attribute name
>> get_attribute name
>> else
>> get_elements_by_tag_name name
>> end
>> end
>>
>> def text
>> inner_text
>> end
>> end
>>
>> My first problem is that I''m getting XmlElement object instead
of
>> XmlNode from an XmlNodeList. If I had XmlNode, then I could do
>> e[''n''].text - which is what I want. As a result, my
code to access
>> the N element looks like this:
>>
>> require ''xml''
>> @document =
Document.new(''<x><x1><n>test</n><z>aaa</z></x1></x>'')
>> @document.get(''x'').collect {|n| puts n.text}
>> >> testaaa
>>
>> >>> @document.get(''x/x1'').collect {|e|
e.get(''n'').collect {|n| puts
>> >>> n.text}}
>> test
>>
>> Why am I getting a XmlElement object? How can I access my xml in a
>> cleaner fashion?
>>
>>
>> My second problem, I wanted to be able to pass in a block
>>
>> def get(xpath)
>> @document.SelectNodes(xpath).collect {yield}
>> end
>>
>> In this case, I get the following error:
>> >>> @document.get(''x'') {|n| puts n.text}
>> :1: undefined method `text'' for nil:NilClass (NoMethodError)
>> from xml.rb:27:in `get''
>>
>> I changed it to {|n| yield}, but I get the same error. The object is
>> always nil. What am I doing wrong?
>>
>> Hope this all makes sense.
>>
>> Thanks
>>
>> Ben
>> _______________________________________________
>> Ironruby-core mailing list
>> Ironruby-core at rubyforge.org
>> http://rubyforge.org/mailman/listinfo/ironruby-core
>
>
> _______________________________________________
> Ironruby-core mailing list
> Ironruby-core at rubyforge.org
> http://rubyforge.org/mailman/listinfo/ironruby-core
>
>