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 > >