Forum: IronRuby Xml Processing in IronRuby - Help me improve the wrapper

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
Ben H. (Guest)
on 2009-01-01 19:49
(Received via mailing list)
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 P. (Guest)
on 2009-01-01 20:02
(Received via mailing list)
I wrote something similar a while ago

http://github.com/casualjim/ironnails/tree/master/...

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 :)
Ben H. (Guest)
on 2009-01-01 20:42
(Received via mailing list)
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
This topic is locked and can not be replied to.