rubyxmlbuilder

Builder XML dynamic elements


I am trying to run though a program and dynamically assign elements using the builder methods. While stepping through my procedure I am attempting to dynamically assign elements using variables. I have attempted a few options to have this variable pass though into the element but it is not working.

I originally started by building my data in a hash however in my full procedure I have duplicate keys, so i had to move to something more direct.

is it possible to achive my desired effect using builder

require 'builder'
x = Builder::XmlMarkup.new(:target => $stdout, :indent => 1)
x.instruct!
x.character do
  stats = "health, mana, armor"
  stats.split(",").each do |stat|
    key = stat.strip.downcase
    value = rand()
    x.key value
  end #end do
end #end do

Output

C:\Projects>ruby test.rb
<?xml version="1.0" encoding="UTF-8"?>
<character>
 <key>0.1405191069855357</key>
 <key>0.3484226234753265</key>
 <key>0.4658284443108096</key>
</character>

Desired output

C:\Projects>ruby test.rb
<?xml version="1.0" encoding="UTF-8"?>
<character>
 <health>0.1405191069855357</health>
 <mana>0.3484226234753265</mana>
 <armor>0.4658284443108096</armor>
</character>

Solution

  • require 'builder'
    x = Builder::XmlMarkup.new(:target => $stdout, :indent => 1)
    x.instruct!
    x.character do
      stats = "health, mana, armor"
      stats.split(",").each do |stat|
        key = stat.strip.downcase
        value = rand()
        x.__send__(key, value)
      end
    end
    

    you can used ruby object method send or its alias __send__. But since, send word can also be used for its key, only __send__ is exposed for use to the object. The doc for the mentioned methods: https://ruby-doc.org/core-2.6.5/Object.html#method-i-send

    Invokes the method identified by symbol, passing it any arguments specified. You can use __send__ if the name send clashes with an existing method in obj. When the method is identified by a string, the string is converted to a symbol.

    Just make sure to try limiting the scope of its usage since it's a powerful method, it can easily break stuffs.