diff --git a/lib/gyoku/array.rb b/lib/gyoku/array.rb index 8be6cc8..4b1272d 100644 --- a/lib/gyoku/array.rb +++ b/lib/gyoku/array.rb @@ -9,8 +9,11 @@ class Array # Translates a given +array+ to XML. Accepts the XML +key+ to add the elements to, # whether to +escape_xml+ and an optional Hash of +attributes+. def self.to_xml(array, key, escape_xml = true, attributes = {}, options = {}) + options[:builder] ||= {} + options[:builder][:indent] ||= 0 + options[:builder][:margin] ||= 0 self_closing = options.delete(:self_closing) - iterate_with_xml array, attributes do |xml, item, attrs, index| + iterate_with_xml array, attributes, options do |xml, item, attrs, index| if self_closing xml.tag!(key, attrs) @@ -18,7 +21,7 @@ def self.to_xml(array, key, escape_xml = true, attributes = {}, options = {}) case item when ::Hash then xml.tag!(key, attrs) { xml << Hash.to_xml(item, options) } when NilClass then xml.tag!(key, "xsi:nil" => "true") - else xml.tag!(key, attrs) { xml << XMLValue.create(item, escape_xml) } + else xml.tag!(key, attrs, false, XMLValue.create(item, escape_xml)) end end end @@ -28,8 +31,9 @@ def self.to_xml(array, key, escape_xml = true, attributes = {}, options = {}) # Iterates over a given +array+ with a Hash of +attributes+ and yields a builder +xml+ # instance, the current +item+, any XML +attributes+ and the current +index+. - def self.iterate_with_xml(array, attributes) - xml = Builder::XmlMarkup.new + def self.iterate_with_xml(array, attributes, options = {}) + xml = Builder::XmlMarkup.new(options[:builder] || {}) + options[:builder][:margin] += 1 array.each_with_index do |item, index| if item.respond_to?(:keys) attrs = item.reduce({}) do |st, v| @@ -42,6 +46,7 @@ def self.iterate_with_xml(array, attributes) end yield xml, item, tag_attributes(attributes, index).merge(attrs), index end + options[:builder][:margin] -= 1 xml.target! end diff --git a/lib/gyoku/hash.rb b/lib/gyoku/hash.rb index 6ff2509..0678baf 100644 --- a/lib/gyoku/hash.rb +++ b/lib/gyoku/hash.rb @@ -9,7 +9,10 @@ class Hash # Translates a given +hash+ with +options+ to XML. def self.to_xml(hash, options = {}) - iterate_with_xml hash do |xml, key, value, attributes| + options[:builder] ||= {} + options[:builder][:indent] ||= 0 + options[:builder][:margin] ||= 0 + iterate_with_xml hash, options do |xml, key, value, attributes| self_closing = key.to_s[-1, 1] == "/" escape_xml = key.to_s[-1, 1] != "!" xml_key = XMLKey.create key, options @@ -20,7 +23,7 @@ def self.to_xml(hash, options = {}) when ::Hash === value then xml.tag!(xml_key, attributes) { xml << Hash.to_xml(value, options) } when self_closing then xml.tag!(xml_key, attributes) when NilClass === value then xml.tag!(xml_key, "xsi:nil" => "true") - else xml.tag!(xml_key, attributes) { xml << XMLValue.create(value, escape_xml) } + else xml.tag!(xml_key, attributes, false, XMLValue.create(value, escape_xml)) end end end @@ -33,11 +36,12 @@ def self.to_xml(hash, options = {}) # Keys beginning with "@" are treated as explicit attributes for their container. # You can use both :attributes! and "@" keys to specify attributes. # In the event of a conflict, the "@" key takes precedence. - def self.iterate_with_xml(hash) - xml = Builder::XmlMarkup.new + def self.iterate_with_xml(hash, options = {}) + xml = Builder::XmlMarkup.new(options[:builder] || {}) attributes = hash[:attributes!] || {} hash_without_attributes = hash.reject { |key, value| key == :attributes! } + options[:builder][:margin] += 1 order(hash_without_attributes).each do |key| node_attr = attributes[key] || {} # node_attr must be kind of ActiveSupport::HashWithIndifferentAccess @@ -57,6 +61,7 @@ def self.iterate_with_xml(hash) yield xml, key, node_value, node_attr end + options[:builder][:margin] -= 1 xml.target! end diff --git a/spec/gyoku/array_spec.rb b/spec/gyoku/array_spec.rb index 1921dc0..431352a 100644 --- a/spec/gyoku/array_spec.rb +++ b/spec/gyoku/array_spec.rb @@ -51,6 +51,12 @@ to_xml(array, "value", :escape_xml, :id => [1, 2]).should == result end + + it "should pass options to XML Builder" do + array = [{ :name => "adam" }, { :name => "eve" }] + result = "\n adam\n\n\n eve\n\n" + to_xml(array, "user", true, {}, { :builder => {:indent => 2} }).should == result + end end def to_xml(*args) diff --git a/spec/gyoku/hash_spec.rb b/spec/gyoku/hash_spec.rb index c1f84cc..fe2afb7 100644 --- a/spec/gyoku/hash_spec.rb +++ b/spec/gyoku/hash_spec.rb @@ -298,6 +298,12 @@ def singleton.to_datetime :attributes! => { :countries => { :array => true } } } end + + it "should pass options to XML Builder" do + hash = {:some => { :new => "user" }} + result = "\n user\n\n" + to_xml(hash, { :builder => {:indent => 2} }).should == result + end end it "doesn't modify original hash parameter by deleting its attribute keys" do