gyoku-1.4.0/ 0000755 0000041 0000041 00000000000 14235144521 012703 5 ustar www-data www-data gyoku-1.4.0/.rspec 0000644 0000041 0000041 00000000010 14235144521 014007 0 ustar www-data www-data --color
gyoku-1.4.0/README.md 0000644 0000041 0000041 00000020532 14235144521 014164 0 ustar www-data www-data # Gyoku
Gyoku translates Ruby Hashes to XML.
``` ruby
Gyoku.xml(:find_user => { :id => 123, "v1:Key" => "api" })
# => "123api"
```
[](https://github.com/savonrb/gyoku/actions/workflows/ci.yml)
[](http://badge.fury.io/rb/gyoku)
[](https://codeclimate.com/github/savonrb/gyoku)
[](https://coveralls.io/r/savonrb/gyoku)
## Installation
Gyoku is available through [Rubygems](http://rubygems.org/gems/gyoku) and can be installed via:
``` bash
$ gem install gyoku
```
or add it to your Gemfile like this:
``` ruby
gem 'gyoku', '~> 1.0'
```
## Hash keys
Hash key Symbols are converted to lowerCamelCase Strings.
``` ruby
Gyoku.xml(:lower_camel_case => "key")
# => "key"
```
You can change the default conversion formula to `:camelcase`, `:upcase` or `:none`.
Note that options are passed as a second Hash to the `.xml` method.
``` ruby
Gyoku.xml({ :camel_case => "key" }, { :key_converter => :camelcase })
# => "key"
```
Custom key converters. You can use a lambda/Proc to provide customer key converters.
This is a great way to leverage active support inflections for domain specific acronyms.
``` ruby
# Use camelize lower which will hook into active support if installed.
Gyoku.xml({ acronym_abc: "value" }, key_converter: lambda { |key| key.camelize(:lower) })
# => "value"
```
Hash key Strings are not converted and may contain namespaces.
``` ruby
Gyoku.xml("XML" => "key")
# => "key"
```
## Hash values
* DateTime objects are converted to xs:dateTime Strings
* Objects responding to :to_datetime (except Strings) are converted to xs:dateTime Strings
* TrueClass and FalseClass objects are converted to "true" and "false" Strings
* NilClass objects are converted to xsi:nil tags
* These conventions are also applied to the return value of objects responding to :call
* All other objects are converted to Strings using :to_s
## Array values
Array items are by default wrapped with the containiner tag, which may be unexpected.
``` ruby
> Gyoku.xml({languages: [{language: 'ruby'},{language: 'java'}]})
# => "rubyjava"
```
You can set the `unwrap` option to remove this behavior.
``` ruby
> Gyoku.xml({languages: [{language: 'ruby'},{language: 'java'}]}, { unwrap: true})
# => "rubyjava"
```
## Special characters
Gyoku escapes special characters unless the Hash key ends with an exclamation mark.
``` ruby
Gyoku.xml(:escaped => "", :not_escaped! => "")
# => "<tag />"
```
## Self-closing tags
Hash Keys ending with a forward slash create self-closing tags.
``` ruby
Gyoku.xml(:"self_closing/" => "", "selfClosing/" => nil)
# => ""
```
## Sort XML tags
In case you need the XML tags to be in a specific order, you can specify the order
through an additional Array stored under the `:order!` key.
``` ruby
Gyoku.xml(:name => "Eve", :id => 1, :order! => [:id, :name])
# => "1Eve"
```
## XML attributes
Adding XML attributes is rather ugly, but it can be done by specifying an additional
Hash stored under the`:attributes!` key.
``` ruby
Gyoku.xml(:person => "Eve", :attributes! => { :person => { :id => 1 } })
# => "Eve"
```
## Explicit XML Attributes
In addition to using the `:attributes!` key, you may also specify attributes through keys beginning with an "@" sign.
Since you'll need to set the attribute within the hash containing the node's contents, a `:content!` key can be used
to explicity set the content of the node. The `:content!` value may be a String, Hash, or Array.
This is particularly useful for self-closing tags.
**Using :attributes!**
``` ruby
Gyoku.xml(
"foo/" => "",
:attributes! => {
"foo/" => {
"bar" => "1",
"biz" => "2",
"baz" => "3"
}
}
)
# => ""
```
**Using "@" keys and ":content!"**
``` ruby
Gyoku.xml(
"foo/" => {
:@bar => "1",
:@biz => "2",
:@baz => "3",
:content! => ""
})
# => ""
```
**Example using "@" to get Array of parent tags each with @attributes & :content!**
``` ruby
Gyoku.xml(
"foo" => [
{:@name => "bar", :content! => 'gyoku'}
{:@name => "baz", :@some => "attr", :content! => 'rocks!'}
])
# => "gyokurocks!"
```
Unwrapping Arrays. You can specify an optional `unwrap` argument to modify the default Array
behavior. `unwrap` accepts a boolean flag (false by default) or an Array whitelist of keys to unwrap.
``` ruby
# Default Array behavior
Gyoku.xml({
"foo" => [
{:is => 'great' },
{:is => 'awesome'}
]
})
# => "greatawesome"
# Unwrap Array behavior
Gyoku.xml({
"foo" => [
{:is => 'great' },
{:is => 'awesome'}
]
}, unwrap: true)
# => "greatawesome"
# Unwrap Array, whitelist.
# foo is not unwrapped, bar is.
Gyoku.xml({
"foo" => [
{:is => 'great' },
{:is => 'awesome'}
],
"bar" => [
{:is => 'rad' },
{:is => 'cool'}
]
}, unwrap: [:bar])
# => "greatawesomeradcool"
```
Naturally, it would ignore :content! if tag is self-closing:
``` ruby
Gyoku.xml(
"foo/" => [
{:@name => "bar", :content! => 'gyoku'}
{:@name => "baz", :@some => "attr", :content! => 'rocks!'}
])
# => ""
```
This seems a bit more explicit with the attributes rather than having to maintain a hash of attributes.
For backward compatibility, `:attributes!` will still work. However, "@" keys will override `:attributes!` keys
if there is a conflict.
``` ruby
Gyoku.xml(:person => {:content! => "Adam", :@id! => 0})
# => "Adam"
```
**Example with ":content!", :attributes! and "@" keys**
``` ruby
Gyoku.xml({
:subtitle => {
:@lang => "en",
:content! => "It's Godzilla!"
},
:attributes! => { :subtitle => { "lang" => "jp" } }
}
# => "It's Godzilla!"
```
The example above shows an example of how you can use all three at the same time.
Notice that we have the attribute "lang" defined twice.
The `@lang` value takes precedence over the `:attribute![:subtitle]["lang"]` value.
## Pretty Print
You can prettify the output XML to make it more readable. Use these options:
* `pretty_print` – controls pretty mode (default: `false`)
* `indent` – specifies indentation in spaces (default: `2`)
* `compact` – controls compact mode (default: `true`)
**This feature is not available for XML documents generated from arrays with unwrap option set to false as such documents are not valid**
**Examples**
``` ruby
puts Gyoku.xml({user: { name: 'John', job: { title: 'Programmer' }, :@status => 'active' }}, pretty_print: true)
#
# John
#
# Programmer
#
#
```
``` ruby
puts Gyoku.xml({user: { name: 'John', job: { title: 'Programmer' }, :@status => 'active' }}, pretty_print: true, indent: 4)
#
# John
#
# Programmer
#
#
```
``` ruby
puts Gyoku.xml({user: { name: 'John', job: { title: 'Programmer' }, :@status => 'active' }}, pretty_print: true, compact: false)
#
#
# John
#
#
#
# Programmer
#
#
#
```
**Generate XML from an array with `unwrap` option set to `true`**
``` ruby
puts Gyoku::Array.to_xml(["john", "jane"], "user", true, {}, pretty_print: true, unwrap: true)
#
# john
# jane
#
```
**Generate XML from an array with `unwrap` option unset (`false` by default)**
``` ruby
puts Gyoku::Array.to_xml(["john", "jane"], "user", true, {}, pretty_print: true)
#johnjane
```
gyoku-1.4.0/spec/ 0000755 0000041 0000041 00000000000 14235144521 013635 5 ustar www-data www-data gyoku-1.4.0/spec/gyoku_spec.rb 0000644 0000041 0000041 00000004742 14235144521 016341 0 ustar www-data www-data require "spec_helper"
describe Gyoku do
describe ".xml_tag" do
it "translates Symbols to lowerCamelCase by default" do
tag = Gyoku.xml_tag(:user_name)
expect(tag).to eq("userName")
end
it "does not translate Strings" do
tag = Gyoku.xml_tag("user_name")
expect(tag).to eq("user_name")
end
it "translates Symbols by a given key_converter" do
tag = Gyoku.xml_tag(:user_name, :key_converter => :upcase)
expect(tag).to eq("USER_NAME")
end
it "does not translates Strings with a given key_converter" do
tag = Gyoku.xml_tag("user_name", :key_converter => :upcase)
expect(tag).to eq("user_name")
end
end
describe ".xml" do
it "translates a given Hash to XML" do
hash = { :id => 1 }
xml = Gyoku.xml(hash, :element_form_default => :qualified)
expect(xml).to eq("1")
end
it "accepts a key_converter for the Hash keys" do
hash = { :user_name => "finn", :pass_word => "secret" }
xml = Gyoku.xml(hash, {key_converter: :upcase})
expect(xml).to include("finn")
expect(xml).to include("secret")
end
it "don't converts Strings keys" do
hash = { :user_name => "finn", "pass_word" => "secret" }
xml = Gyoku.xml(hash, {key_converter: :upcase})
expect(xml).to include("finn")
expect(xml).to include("secret")
end
it "when defined key_to_convert only convert this key" do
hash = { user_name: "finn", pass_word: "secret" }
options = {key_converter: :upcase, key_to_convert: 'user_name'}
xml = Gyoku.xml(hash, options)
expect(xml).to include("finn")
expect(xml).to include("secret")
end
it "accepts key_converter for nested hash" do
hash = { user: { user_name: "finn", pass_word: "secret" }}
xml = Gyoku.xml(hash, {key_converter: :upcase})
expect(xml).to include("finn")
expect(xml).to include("secret")
end
it "does not modify the original Hash" do
hash = {
:person => {
:first_name => "Lucy",
:last_name => "Sky",
:order! => [:first_name, :last_name]
},
:attributes! => { :person => { :id => "666" } }
}
original_hash = hash.dup
Gyoku.xml(hash)
expect(original_hash).to eq(hash)
end
end
end
gyoku-1.4.0/spec/gyoku/ 0000755 0000041 0000041 00000000000 14235144521 014773 5 ustar www-data www-data gyoku-1.4.0/spec/gyoku/prettifier_spec.rb 0000644 0000041 0000041 00000002264 14235144521 020513 0 ustar www-data www-data require "spec_helper"
describe Gyoku::Prettifier do
describe "#prettify" do
context "when xml is valid" do
let!(:xml) { Gyoku::Hash.build_xml(test: { pretty: "xml" }) }
it "returns prettified xml" do
expect(subject.prettify(xml)).to eql("\n xml\n")
end
context "when indent option is specified" do
it "returns prettified xml with indent" do
options = { indent: 3 }
subject = Gyoku::Prettifier.new(options)
expect(subject.prettify(xml)).to eql("\n xml\n")
end
end
context "when compact option is specified" do
it "returns prettified xml with indent" do
options = { compact: false }
subject = Gyoku::Prettifier.new(options)
expect(subject.prettify(xml)).to eql("\n \n xml\n \n")
end
end
end
context "when xml is not valid" do
let!(:xml) do
Gyoku::Array.build_xml(["one", "two"], "test")
end
it "raises an error" do
expect{ subject.prettify(xml) }.to raise_error REXML::ParseException
end
end
end
end
gyoku-1.4.0/spec/gyoku/array_spec.rb 0000644 0000041 0000041 00000010554 14235144521 017455 0 ustar www-data www-data require "spec_helper"
describe Gyoku::Array do
describe ".to_xml" do
it "returns the XML for an Array of Hashes" do
array = [{ :name => "adam" }, { :name => "eve" }]
result = "adameve"
expect(to_xml(array, "user")).to eq(result)
end
it "returns the XML for an Array of Hashes unwrapped" do
array = [{ :name => "adam" }, { :name => "eve" }]
result = "adameve"
expect(to_xml(array, "user", true, {}, :unwrap => true)).to eq(result)
end
it "returns the XML for an Array of different Objects" do
array = [:symbol, "string", 123]
result = "symbolstring123"
expect(to_xml(array, "value")).to eq(result)
end
it "defaults to escape special characters" do
array = ["", "adam & eve"]
result = "<tag />adam & eve"
expect(to_xml(array, "value")).to eq(result)
end
it "does not escape special characters when told to" do
array = ["", "adam & eve"]
result = "adam & eve"
expect(to_xml(array, "value", false)).to eq(result)
end
it "adds attributes to a given tag" do
array = ["adam", "eve"]
result = 'adameve'
expect(to_xml(array, "value", :escape_xml, :active => true)).to eq(result)
end
it "adds attributes to tags when :unwrap is true" do
array = [{:item=>"abc"}]
key = "items"
escape_xml = :escape_xml
attributes = { "amount"=>"1" }
options = { :unwrap => true }
result = "abc"
expect(to_xml(array, key, escape_xml, attributes, options)).to eq result
end
it "adds attributes to duplicate tags" do
array = ["adam", "eve"]
result = 'adameve'
expect(to_xml(array, "value", :escape_xml, :id => [1, 2])).to eq(result)
end
it "skips attribute for element without attributes if there are fewer attributes than elements" do
array = ["adam", "eve", "serpent"]
result = 'adameveserpent'
expect(to_xml(array, "value", :escape_xml, :id => [1, 2])).to eq(result)
end
it "handles nested Arrays" do
array = [["one", "two"]]
result = "onetwo"
expect(to_xml(array, "value")).to eq(result)
end
context "when :pretty_print option is set to true" do
context "when :unwrap option is set to true" do
it "returns prettified xml" do
array = ["one", "two", {"three" => "four"}]
options = { pretty_print: true, unwrap: true }
result = "\n one\n two\n four\n"
expect(to_xml(array, "test", true, {}, options)).to eq(result)
end
context "when :indent option is specified" do
it "returns prettified xml with specified indent" do
array = ["one", "two", {"three" => "four"}]
options = { pretty_print: true, indent: 3, unwrap: true }
result = "\n one\n two\n four\n"
expect(to_xml(array, "test", true, {}, options)).to eq(result)
end
end
context "when :compact option is specified" do
it "returns prettified xml with specified compact mode" do
array = ["one", {"two" => "three"}]
options = { pretty_print: true, compact: false, unwrap: true }
result = "\n \n one\n \n \n three \n \n"
expect(to_xml(array, "test", true, {}, options)).to eq(result)
end
end
end
context "when :unwrap option is not set" do
it "returns non-prettified xml" do
array = ["one", "two", {"three" => "four"}]
options = { pretty_print: true }
result = "onetwofour"
expect(to_xml(array, "test", true, {}, options)).to eq(result)
end
end
end
end
def to_xml(*args)
Gyoku::Array.to_xml *args
end
end
gyoku-1.4.0/spec/gyoku/xml_key_spec.rb 0000644 0000041 0000041 00000005453 14235144521 020011 0 ustar www-data www-data require "spec_helper"
describe Gyoku::XMLKey do
describe ".create" do
it "removes exclamation marks from the end of a String" do
expect(create("value!")).to eq("value")
end
it "removes forward slashes from the end of a String" do
expect(create("self-closing/")).to eq("self-closing")
end
it "does not convert snake_case Strings" do
expect(create("lower_camel_case")).to eq("lower_camel_case")
end
it "converts snake_case Symbols to lowerCamelCase Strings" do
expect(create(:lower_camel_case)).to eq("lowerCamelCase")
expect(create(:lower_camel_case!)).to eq("lowerCamelCase")
end
context "when the converter option is set to camelcase" do
it "should replace / with ::, and turn snake case into camel case" do
input = "hello_world_bob/how_are_you|there:foo^bar".to_sym
expected_output = "HelloWorldBob::HowAreYou|there:foo^bar"
expect(create(input, {key_converter: :camelcase})).to eq(expected_output)
end
end
context "with key_converter" do
it "accepts lambda converters" do
expect(create(:some_text, {key_converter: lambda { |k| k.reverse }})).to eq("txet_emos")
end
it "convert symbol to the specified type" do
expect(create(:some_text, {key_converter: :camelcase})).to eq("SomeText")
expect(create(:some_text, {key_converter: :upcase})).to eq("SOME_TEXT")
expect(create(:some_text, {key_converter: :none})).to eq("some_text")
end
it "when key_to_convert is defined, convert only this key" do
options = {key_converter: :camelcase, key_to_convert: 'somekey'}
expect(create(:some_key, options)).to eq("someKey")
options = {key_converter: :camelcase, key_to_convert: 'some_key'}
expect(create(:some_key, options)).to eq("SomeKey")
end
it "when except is defined, dont convert this key" do
options = {key_converter: :camelcase, except: 'some_key'}
expect(create(:some_key, options)).to eq("someKey")
end
end
context "with :element_form_default set to :qualified and a :namespace" do
it "adds the given namespace" do
key = create :qualify, :element_form_default => :qualified, :namespace => :v1
expect(key).to eq("v1:qualify")
end
it "does not add the given namespace if the key starts with a colon" do
key = create ":qualify", :element_form_default => :qualified, :namespace => :v1
expect(key).to eq("qualify")
end
it "adds a given :namespace after converting the key" do
key = create :username, :element_form_default => :qualified, :namespace => :v1, :key_converter => :camelcase
expect(key).to eq("v1:Username")
end
end
end
def create(key, options = {})
Gyoku::XMLKey.create(key, options)
end
end
gyoku-1.4.0/spec/gyoku/xml_value_spec.rb 0000644 0000041 0000041 00000004106 14235144521 020327 0 ustar www-data www-data require "spec_helper"
describe Gyoku::XMLValue do
describe ".create" do
context "for DateTime objects" do
it "returns an xs:dateTime compliant String" do
expect(create(DateTime.new(2012, 03, 22, 16, 22, 33))).to eq("2012-03-22T16:22:33+00:00")
end
end
context "for Date objects" do
it "returns an xs:date compliant String" do
expect(create(Date.new(2012, 03, 22))).to eq("2012-03-22")
end
end
context "for Time objects" do
it "returns an xs:time compliant String" do
expect(create(Time.local(2012, 03, 22, 16, 22, 33))).to eq("16:22:33")
end
end
it "returns the String value and escapes special characters" do
expect(create("string")).to eq("string")
expect(create("")).to eq("<tag>")
expect(create("at&t")).to eq("at&t")
expect(create('"quotes"')).to eq(""quotes"")
end
it "returns the String value without escaping special characters" do
expect(create("", false)).to eq("")
end
it "returns an xs:dateTime compliant String for Objects responding to #to_datetime" do
singleton = Object.new
def singleton.to_datetime
DateTime.new 2012, 03, 22, 16, 22, 33
end
expect(create(singleton)).to eq("2012-03-22T16:22:33+00:00")
end
it "calls Proc objects and converts their return value" do
object = lambda { DateTime.new 2012, 03, 22, 16, 22, 33 }
expect(create(object)).to eq("2012-03-22T16:22:33+00:00")
end
it "hash objects get converted to xml" do
object = { document!: { "@version" => "2.0", content!: { key!: "value", other_key: { "@attribute" => 'value', content!: { key: "value" } } } } }
expect(create(object)).to eq("valuevalue")
end
it "calls #to_s unless the Object responds to #to_datetime" do
expect(create("value")).to eq("value")
end
end
def create(object, escape_xml = true)
Gyoku::XMLValue.create object, escape_xml
end
end
gyoku-1.4.0/spec/gyoku/hash_spec.rb 0000644 0000041 0000041 00000036317 14235144521 017267 0 ustar www-data www-data require "spec_helper"
describe Gyoku::Hash do
describe ".to_xml" do
describe "returns SOAP request compatible XML" do
it "for a simple Hash" do
expect(to_xml(:some => "user")).to eq("user")
end
it "for a nested Hash" do
expect(to_xml(:some => { :new => "user" })).to eq("user")
end
context "with key_converter" do
it "expect all keys change" do
expect(to_xml({:some => { :new => "user" }}, {key_converter: :camelcase})).to eq("user")
end
it "and key_to_convert option should change only key" do
hash = {:some => { :new => "user", :age => 20 }}
options = {key_converter: :camelcase, key_to_convert: "some"}
result = "user20"
expect(to_xml(hash, options)).to eq(result)
hash = {:some => { :new => "user", :age => 20 }}
options = {key_converter: :camelcase, key_to_convert: "new"}
result = "user20"
expect(to_xml(hash, options)).to eq(result)
end
it "with except option, dont convert this key" do
hash = {:some => { :new => "user", :age => 20 }}
options = {key_converter: :camelcase, except: "some"}
result = "user20"
expect(to_xml(hash, options)).to eq(result)
end
end
it "for a Hash with multiple keys" do
expect(to_xml(:all => "users", :before => "whatever")).to include(
"users",
"whatever"
)
end
it "for a Hash containing an Array" do
expect(to_xml(:some => ["user", "gorilla"])).to eq("usergorilla")
end
it "for a Hash containing an Array of Hashes" do
expect(to_xml(:some => [{ :new => "user" }, { :old => "gorilla" }])).
to eq("usergorilla")
end
context "when :pretty_print option is set to true" do
it "returns prettified xml" do
hash = { some: { user: { name: "John", groups: ["admin", "editor"] } } }
options = { pretty_print: true }
result = "\n \n John\n admin\n editor\n \n"
expect(to_xml(hash, options)).to eq(result)
end
context "when :indent option is specified" do
it "returns prettified xml with specified indent" do
hash = { some: { user: { name: "John" } } }
options = { pretty_print: true, indent: 4 }
result = "\n \n John\n \n"
expect(to_xml(hash, options)).to eq(result)
end
end
context "when :compact option is specified" do
it "returns prettified xml with specified compact mode" do
hash = { some: { user: { name: "John" } } }
options = { pretty_print: true, compact: false }
result = "\n \n \n John\n \n \n"
expect(to_xml(hash, options)).to eq(result)
end
end
end
end
it "converts Hash key Symbols to lowerCamelCase" do
expect(to_xml(:find_or_create => "user")).to eq("user")
end
it "does not convert Hash key Strings" do
expect(to_xml("find_or_create" => "user")).to eq("user")
end
it "converts DateTime objects to xs:dateTime compliant Strings" do
expect(to_xml(:before => DateTime.new(2012, 03, 22, 16, 22, 33))).
to eq("2012-03-22T16:22:33+00:00")
end
it "converts Objects responding to to_datetime to xs:dateTime compliant Strings" do
singleton = Object.new
def singleton.to_datetime
DateTime.new(2012, 03, 22, 16, 22, 33)
end
expect(to_xml(:before => singleton)).to eq("2012-03-22T16:22:33+00:00")
end
it "calls to_s on Strings even if they respond to to_datetime" do
singleton = "gorilla"
def singleton.to_datetime
DateTime.new(2012, 03, 22, 16, 22, 33)
end
expect(to_xml(:name => singleton)).to eq("gorilla")
end
it "properly serializes nil values" do
expect(to_xml(:some => nil)).to eq('')
end
it "creates self-closing tags for Hash keys ending with a forward slash" do
expect(to_xml("self-closing/" => nil)).to eq('')
end
it "calls to_s on any other Object" do
[666, true, false].each do |object|
expect(to_xml(:some => object)).to eq("#{object}")
end
end
it "defaults to escape special characters" do
result = to_xml(:some => { :nested => "" }, :tag => "")
expect(result).to include("<tag />")
expect(result).to include("<tag />")
end
it "does not escape special characters for keys marked with an exclamation mark" do
result = to_xml(:some => { :nested! => "" }, :tag! => "")
expect(result).to include("")
expect(result).to include("")
end
it "preserves the order of Hash keys and values specified through :order!" do
hash = { :find_user => { :name => "Lucy", :id => 666, :order! => [:id, :name] } }
result = "666Lucy"
expect(to_xml(hash)).to eq(result)
hash = { :find_user => { :mname => "in the", :lname => "Sky", :fname => "Lucy", :order! => [:fname, :mname, :lname] } }
result = "Lucyin theSky"
expect(to_xml(hash)).to eq(result)
end
it "preserves the order of Hash keys and values specified through 'order!' (as a string key)" do
hash = { :find_user => { :name => "Lucy", :id => 666, 'order!' => [:id, :name] } }
result = "666Lucy"
expect(to_xml(hash)).to eq(result)
hash = { :find_user => { :mname => "in the", :lname => "Sky", :fname => "Lucy", 'order!' => [:fname, :mname, :lname] } }
result = "Lucyin theSky"
expect(to_xml(hash)).to eq(result)
end
it "uses :order! symbol values for ordering but leaves the string key 'order!' if both are present" do
hash = { :find_user => { :name => "Lucy", :id => 666, 'order!' => 'value', :order! => [:id, :name, 'order!'] } }
result = "666Lucyvalue"
expect(to_xml(hash)).to eq(result)
end
it "raises if the :order! Array is missing Hash keys" do
hash = { :name => "Lucy", :id => 666, :order! => [:name] }
expect { to_xml(hash) }.to raise_error(ArgumentError, "Missing elements in :order! [:id]")
end
it "raises if the :order! Array contains missing Hash keys" do
hash = { :by_name => { :first_name => "Lucy", :last_name => "Sky", :order! => [:first_name, :middle_name, :last_name] } }
expect { to_xml(hash) }.to raise_error(ArgumentError, "Spurious elements in :order! [:middle_name]")
end
it "adds attributes to Hash keys specified through :attributes!" do
hash = { :find_user => { :person => "Lucy", :attributes! => { :person => { :id => 666 } } } }
result = 'Lucy'
expect(to_xml(hash)).to eq(result)
hash = { :find_user => { :person => "Lucy", :attributes! => { :person => { :id => 666, :city => "Hamburg" } } } }
expect(to_xml(hash)).to include('id="666"', 'city="Hamburg"')
end
it "adds attributes to duplicate Hash keys specified through :attributes!" do
hash = { :find_user => { :person => ["Lucy", "Anna"], :attributes! => { :person => { :id => [1, 3] } } } }
result = 'LucyAnna'
expect(to_xml(hash)).to eq(result)
hash = { :find_user => { :person => ["Lucy", "Anna"], :attributes! => { :person => { :active => "true" } } } }
result = 'LucyAnna'
expect(to_xml(hash)).to eq(result)
end
it "skips attribute for element without attributes if there are fewer attributes than elements" do
hash = { :find_user => { :person => ["Lucy", "Anna", "Beth"], :attributes! => { :person => { :id => [1, 3] } } } }
result = 'LucyAnnaBeth'
expect(to_xml(hash)).to eq(result)
end
it "adds attributes to self-closing tags" do
hash = {
"category/" => "",
:attributes! => { "category/" => { :id => 1 } }
}
expect(to_xml(hash)).to eq('')
end
it "recognizes @attribute => value along :attributes!" do
hash = {
"category" => {
:content! => "users",
:@id => 1
}
}
expect(to_xml(hash)).to eq('users')
end
it "recognizes @attribute => value along :attributes! in selfclosed tags" do
hash = {
"category/" => {
:@id => 1
}
}
expect(to_xml(hash)).to eq('')
end
it ":@attribute => value takes over :attributes!" do
hash = {
"category/" => {
:@id => 1
},
:attributes! => {
"category/" => {
'id' => 2, # will be ignored
'type' => 'admins'
}
}
}
# attribute order is undefined
expect(['','']).to include to_xml(hash)
# with symbols
hash = {
"category/" => {
:@id => 1
},
:attributes! => {
"category/" => {
:id => 2, # will be ignored
:type => 'admins'
}
}
}
expect(['','']).to include to_xml(hash)
end
it "recognizes :content! => value as tag content" do
hash = {
"category" => {
:content! => "users"
}
}
expect(to_xml(hash)).to eq("users")
end
it "recognizes :content! => value as tag content with value Fixnum" do
hash = {
"category" => {
:content! => 666
}
}
expect(to_xml(hash)).to eq("666")
end
it "recognizes :content! => value as tag content with value true" do
hash = {
"category" => {
:content! => true
}
}
expect(to_xml(hash)).to eq("true")
end
it "recognizes :content! => value as tag content with value false" do
hash = {
"category" => {
:content! => false
}
}
expect(to_xml(hash)).to eq("false")
end
it "recognizes :content! => value as tag content with value DateTime" do
hash = {
"before" => {
:content! => DateTime.new(2012, 03, 22, 16, 22, 33)
}
}
expect(to_xml(hash)).to eq("2012-03-22T16:22:33+00:00")
end
it "ignores :content! if self-closing mark present" do
hash = {
"category/" => {
:content! => "users"
}
}
expect(to_xml(hash)).to eq("")
end
it "recognizes array of attributes" do
hash = {
"category" => [{:@name => 'one'}, {:@name => 'two'}]
}
expect(to_xml(hash)).to eq('')
# issue #31.
hash = {
:order! => ['foo', 'bar'],
'foo' => { :@foo => 'foo' },
'bar' => { :@bar => 'bar', 'baz' => { } },
}
expect(to_xml(hash)).to eq('')
end
it "recognizes array of attributes with content in each" do
hash = {
"foo" => [{:@name => "bar", :content! => 'gyoku'}, {:@name => "baz", :@some => "attr", :content! => 'rocks!'}]
}
expect([
'gyokurocks!',
'gyokurocks!'
]).to include to_xml(hash)
end
it "recognizes array of attributes but ignores content in each if selfclosing" do
hash = {
"foo/" => [{:@name => "bar", :content! => 'gyoku'}, {:@name => "baz", :@some => "attr", :content! => 'rocks!'}]
}
expect([
'',
''
]).to include to_xml(hash)
end
it "recognizes array of attributes with selfclosing tag" do
hash = {
"category/" => [{:@name => 'one'}, {:@name => 'two'}]
}
expect(to_xml(hash)).to eq('')
end
context "with :element_form_default set to :qualified and a :namespace" do
it "adds the given :namespace to every element" do
hash = { :first => { "first_name" => "Lucy" }, ":second" => { :":first_name" => "Anna" }, "v2:third" => { "v2:firstName" => "Danie" } }
result = to_xml hash, :element_form_default => :qualified, :namespace => :v1
expect(result).to include(
"Lucy",
"Anna",
"Danie"
)
end
it "adds given :namespace to every element in an array" do
hash = { :array => [ :first => "Lucy", :second => "Anna" ]}
result = to_xml hash, :element_form_default => :qualified, :namespace => :v1
expect(result).to include("", "Lucy", "Anna")
end
end
it "does not remove special keys from the original Hash" do
hash = {
:persons => {
:first => "Lucy",
:second => "Anna",
:order! => [:second, :first],
:attributes! => { :first => { :first => true } }
},
:countries => [:de, :us],
:order! => [:countries, :persons],
:attributes! => { :countries => { :array => true } }
}
to_xml(hash)
expect(hash).to eq({
:persons => {
:first => "Lucy",
:second => "Anna",
:order! => [:second, :first],
:attributes! => { :first => { :first => true } }
},
:countries => [:de, :us],
:order! => [:countries, :persons],
:attributes! => { :countries => { :array => true } }
})
end
end
it "doesn't modify original hash parameter by deleting its attribute keys" do
hash = { :person => {:name => "Johnny", :surname => "Bravo", :"@xsi:type" => "People"} }
to_xml(hash)
expect(hash).to eq({:person=>{:name=>"Johnny", :surname=>"Bravo", :"@xsi:type"=>"People"}})
end
def to_xml(hash, options = {})
Gyoku::Hash.to_xml hash, options
end
end
gyoku-1.4.0/spec/spec_helper.rb 0000644 0000041 0000041 00000000423 14235144521 016452 0 ustar www-data www-data require 'bundler'
Bundler.setup(:default, :development)
unless RUBY_PLATFORM =~ /java/
require 'simplecov'
require 'coveralls'
SimpleCov.formatter = Coveralls::SimpleCov::Formatter
SimpleCov.start do
add_filter 'spec'
end
end
require 'gyoku'
require 'rspec'
gyoku-1.4.0/CHANGELOG.md 0000644 0000041 0000041 00000012015 14235144521 014513 0 ustar www-data www-data # CHANGELOG
## 1.4.0 (2022-04-01)
### Fixed
- Fix [Issue #56](https://github.com/savonrb/gyoku/issue/56) with PR [#57](https://github.com/savonrb/gyoku/pull/57). Thanks, [@jpmoral]!
- Avoid circular reference [#69](https://github.com/savonrb/gyoku/pull/69), thanks [@ccarruitero]!
### Added
- Unwrap specific keys [#54](https://github.com/savonrb/gyoku/pull/54), by [@rlburkes]. Documented by [@mahemoff]. Thanks to you both!
- Add `:pretty_print`, `:indent` and `:compact` options to allow prettified XML output. [#59](https://github.com/savonrb/gyoku/pull/59), by [@Jeiwan]. Thanks!
### Changed
- Removed Rubinius support, by [@olleolleolle]
- Clean-up, CI setup, and changelog authoring, by [@olleolleolle]
[@jpmoral]: https://github.com/jpmoral
[@ccarruitero]: https://github.com/ccarruitero
[@rlburkes]: https://github.com/rlburkes
[@mahemoff]: https://github.com/mahemoff
[@Jeiwan]: https://github.com/Jeiwan
[@olleolleolle]: https://github.com/olleolleolle
## 1.3.1 (2015-04-05)
* Feature: [#53](https://github.com/savonrb/gyoku/pull/53) Improved serialization of hashes nested in arrays. Thanks to @riburkes for this!
## 1.3.0 (2015-03-30)
* Formally drop support for ruby 1.8.7
## 1.2.3 (2015-03-10)
* Feature: [#52](https://github.com/savonrb/gyoku/pull/52) Adds an :unwrap option that allows an array of hashes to be unwrapped into a single array xml node, rather than one per hash.
## 1.2.2 (2014-09-22)
* Fixed a bug introduced by making Gyoku threadsafe. Who knew that `$1` and the block variable that `#gsub` provides are not the same?
## 1.2.1 (2014-09-22)
* Fix : [#46](https://github.com/savonrb/gyoku/pull/46) Fixed an issue where Gyoku was not threadsafe. Gyoku should now be relatively more threadsafe due to less usage of global variables.
## 1.2.0 (2014-09-18)
* Feature: [#44](https://github.com/savonrb/gyoku/pull/44) support for sorting via :order! with a string key
## 1.1.1 (2014-01-02)
* Feature: [#38](https://github.com/savonrb/gyoku/pull/38) support for building nested Arrays
* Feature: [#36](https://github.com/savonrb/gyoku/pull/36) allow setting any objects content with :content!
* Deprecation: Support for ree and ruby 1.8.7 will be going away soon.
## 1.1.0 (2013-07-26)
* Feature: [#30](https://github.com/savonrb/gyoku/pull/30) support for building Arrays
of parent tags using @attributes.
* Fix: [#21](https://github.com/savonrb/gyoku/pull/21) stop modifying the original Hash.
The original issue is [savonrb/savon#410](https://github.com/savonrb/savon/issues/410).
## 1.0.0 (2012-12-17)
* Refactoring: Removed the global configuration. This should really only affect the
`Gyoku.convert_symbols_to` shortcut which was removed as well. If you're using Gyoku
with Savon 2.0, there's now an option for that. If you're using Gyoku on itself,
you can pass it the `:key_converter` option instead.
## 0.5.0 (2012-12-15)
Feature: [#19](https://github.com/savonrb/gyoku/pull/19) adds support for explicit XML attributes.
Feature: [#17](https://github.com/savonrb/gyoku/pull/17) adds an `:upcase` formula.
## 0.4.6 (2012-06-28)
* Fix: [#16](https://github.com/rubiii/gyoku/issues/16) Date objects were mapped like DateTime objects.
Gyoku.xml(date: Date.today) # => "2012-06-28"
* Fix: Time objects were also mapped like DateTime objects.
Gyoku.xml(time: sunday) # => ""
## 0.4.5 (2012-05-28)
* Fix: [issue 8](https://github.com/rubiii/gyoku/issues/8) -
Conflict between camelcase methods in Rails.
* Fix: [pull request 15](https://github.com/rubiii/gyoku/pull/15) -
Gyoku generates blank attribute values if there are fewer attribute
values in attributes! than elements.
* Fix: [issue 12](https://github.com/rubiii/gyoku/issues/12) -
Don't remove special keys from the original Hash.
## 0.4.4
* Fix: [issue 6](https://github.com/rubiii/gyoku/issues/6) -
`Gyoku.xml` does not modify the original Hash.
## 0.4.3
* Fix: Make sure `require "date"` when necessary.
## 0.4.2
* Fix: `Array.to_xml` so that the given :namespace is applied to every element
in an Array.
## 0.4.1
* Fix: Alternative formulas and namespaces.
## 0.4.0
* Feature: Added alternative Symbol conversion formulas. You can choose between
:lower_camelcase (the default), :camelcase and :none.
Gyoku.convert_symbols_to :camelcase
You can even define your own formula:
Gyoku.convert_symbols_to { |key| key.upcase }
## 0.3.1
* Feature: Gyoku now calls Proc objects and converts their return value.
## 0.3.0
* Feature: Now when all Hash keys need to be namespaced (like with
elementFormDefault), you can use options to to trigger this behavior.
Gyoku.xml hash,
:element_form_default => :qualified,
:namespace => :v2
## 0.2.0
* Feature: Added support for self-closing tags. Hash keys ending with a forward
slash (regardless of their value) are now converted to self-closing tags.
## 0.1.1
* Fix: Allow people to use new versions of builder.
## 0.1.0
* Initial version. Gyoku was born as a core extension inside the
[Savon](http://rubygems.org/gems/savon) library.
gyoku-1.4.0/.gitignore 0000644 0000041 0000041 00000000116 14235144521 014671 0 ustar www-data www-data .DS_Store
.yardoc
doc
coverage
tmp
*~
*.swp
*.gem
.bundle
Gemfile.lock
.rvmrc
gyoku-1.4.0/Rakefile 0000644 0000041 0000041 00000000325 14235144521 014350 0 ustar www-data www-data require "bundler"
require "bundler/setup"
Bundler::GemHelper.install_tasks
require "rspec/core/rake_task"
RSpec::Core::RakeTask.new do |t|
t.rspec_opts = %w(-c)
end
task :default => :spec
task :test => :spec
gyoku-1.4.0/lib/ 0000755 0000041 0000041 00000000000 14235144521 013451 5 ustar www-data www-data gyoku-1.4.0/lib/gyoku.rb 0000644 0000041 0000041 00000000516 14235144521 015136 0 ustar www-data www-data require "gyoku/version"
require "gyoku/hash"
module Gyoku
# Converts a given Hash +key+ with +options+ into an XML tag.
def self.xml_tag(key, options = {})
XMLKey.create(key, options)
end
# Translates a given +hash+ with +options+ to XML.
def self.xml(hash, options = {})
Hash.to_xml hash.dup, options
end
end
gyoku-1.4.0/lib/gyoku/ 0000755 0000041 0000041 00000000000 14235144521 014607 5 ustar www-data www-data gyoku-1.4.0/lib/gyoku/version.rb 0000644 0000041 0000041 00000000045 14235144521 016620 0 ustar www-data www-data module Gyoku
VERSION = '1.4.0'
end
gyoku-1.4.0/lib/gyoku/xml_value.rb 0000644 0000041 0000041 00000001741 14235144521 017133 0 ustar www-data www-data require "cgi"
require "date"
module Gyoku
module XMLValue
class << self
# xs:date format
XS_DATE_FORMAT = "%Y-%m-%d"
# xs:time format
XS_TIME_FORMAT = "%H:%M:%S"
# xs:dateTime format
XS_DATETIME_FORMAT = "%Y-%m-%dT%H:%M:%S%Z"
# Converts a given +object+ to an XML value.
def create(object, escape_xml = true, options = {})
if Time === object
object.strftime XS_TIME_FORMAT
elsif DateTime === object
object.strftime XS_DATETIME_FORMAT
elsif Date === object
object.strftime XS_DATE_FORMAT
elsif String === object
escape_xml ? CGI.escapeHTML(object) : object
elsif object.respond_to?(:to_datetime)
create object.to_datetime
elsif object.respond_to?(:call)
create object.call
elsif ::Hash === object
Gyoku::Hash.to_xml(object, options)
else
object.to_s
end
end
end
end
end
gyoku-1.4.0/lib/gyoku/array.rb 0000644 0000041 0000041 00000006311 14235144521 016253 0 ustar www-data www-data require "builder"
require "gyoku/prettifier.rb"
require "gyoku/xml_value"
module Gyoku
class Array
NESTED_ELEMENT_NAME = "element"
# Builds XML and prettifies it if +pretty_print+ option is set to +true+
def self.to_xml(array, key, escape_xml = true, attributes = {}, options = {})
xml = build_xml(array, key, escape_xml, attributes, options)
if options[:pretty_print] && options[:unwrap]
Prettifier.prettify(xml, options)
else
xml
end
end
private
# 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.build_xml(array, key, escape_xml = true, attributes = {}, options = {})
self_closing = options.delete(:self_closing)
unwrap = unwrap?(options.fetch(:unwrap, false), key)
iterate_with_xml array, key, attributes, options do |xml, item, attrs, index|
if self_closing
xml.tag!(key, attrs)
else
case item
when ::Hash then
if unwrap
xml << Hash.to_xml(item, options)
else
xml.tag!(key, attrs) { xml << Hash.build_xml(item, options) }
end
when ::Array then
xml.tag!(key, attrs) { xml << Array.build_xml(item, NESTED_ELEMENT_NAME) }
when NilClass then
xml.tag!(key, "xsi:nil" => "true")
else
xml.tag!(key, attrs) { xml << XMLValue.create(item, escape_xml) }
end
end
end
end
# 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, key, attributes, options, &block)
xml = Builder::XmlMarkup.new
unwrap = unwrap?(options.fetch(:unwrap, false), key)
if unwrap
xml.tag!(key, attributes) { iterate_array(xml, array, attributes, &block) }
else
iterate_array(xml, array, attributes, &block)
end
xml.target!
end
# 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_array(xml, array, attributes, &block)
array.each_with_index do |item, index|
if item.respond_to?(:keys)
attrs = item.reduce({}) do |st, v|
k = v[0].to_s
st[k[1..-1]] = v[1].to_s if k =~ /^@/
st
end
else
attrs = {}
end
yield xml, item, tag_attributes(attributes, index).merge(attrs), index
end
end
# Takes a Hash of +attributes+ and the +index+ for which to return attributes
# for duplicate tags.
def self.tag_attributes(attributes, index)
return {} if attributes.empty?
attributes.inject({}) do |hash, (key, value)|
value = value[index] if value.kind_of? ::Array
value ? hash.merge(key => value) : hash
end
end
def self.unwrap?(unwrap, key)
unwrap.kind_of?(::Array) ? unwrap.include?(key.to_sym) : unwrap
end
end
end
gyoku-1.4.0/lib/gyoku/hash.rb 0000644 0000041 0000041 00000007350 14235144521 016064 0 ustar www-data www-data require "builder"
require "gyoku/prettifier.rb"
require "gyoku/array"
require "gyoku/xml_key"
require "gyoku/xml_value"
module Gyoku
class Hash
# Builds XML and prettifies it if +pretty_print+ option is set to +true+
def self.to_xml(hash, options = {})
xml = build_xml(hash, options)
if options[:pretty_print]
Prettifier.prettify(xml, options)
else
xml
end
end
private
# Translates a given +hash+ with +options+ to XML.
def self.build_xml(hash, options = {})
iterate_with_xml hash 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
case
when :content! === key then xml << XMLValue.create(value, escape_xml, options)
when ::Array === value then xml << Array.build_xml(value, xml_key, escape_xml, attributes, options.merge(:self_closing => self_closing))
when ::Hash === value then xml.tag!(xml_key, attributes) { xml << build_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, options) }
end
end
end
# Iterates over a given +hash+ and yields a builder +xml+ instance, the current
# Hash +key+ and any XML +attributes+.
#
# 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
attributes = hash[:attributes!] || {}
hash_without_attributes = hash.reject { |key, value| key == :attributes! }
order(hash_without_attributes).each do |key|
node_attr = attributes[key] || {}
# node_attr must be kind of ActiveSupport::HashWithIndifferentAccess
node_attr = ::Hash[node_attr.map { |k,v| [k.to_s, v] }]
node_value = hash[key].respond_to?(:keys) ? hash[key].clone : hash[key]
if node_value.respond_to?(:keys)
explicit_keys = node_value.keys.select{|k| k.to_s =~ /^@/ }
explicit_attr = {}
explicit_keys.each{|k| explicit_attr[k.to_s[1..-1]] = node_value[k]}
node_attr.merge!(explicit_attr)
explicit_keys.each{|k| node_value.delete(k) }
tmp_node_value = node_value.delete(:content!)
node_value = tmp_node_value unless tmp_node_value.nil?
node_value = "" if node_value.respond_to?(:empty?) && node_value.empty?
end
yield xml, key, node_value, node_attr
end
xml.target!
end
# Deletes and returns an Array of keys stored under the :order! key of a given +hash+.
# Defaults to return the actual keys of the Hash if no :order! key could be found.
# Raises an ArgumentError in case the :order! Array does not match the Hash keys.
def self.order(hash)
order = hash[:order!] || hash.delete('order!')
hash_without_order = hash.reject { |key, value| key == :order! }
order = hash_without_order.keys unless order.kind_of? ::Array
# Ignore Explicit Attributes
orderable = order.delete_if{|k| k.to_s =~ /^@/ }
hashable = hash_without_order.keys.select{|k| !(k.to_s =~ /^@/) }
missing, spurious = hashable - orderable, orderable - hashable
raise ArgumentError, "Missing elements in :order! #{missing.inspect}" unless missing.empty?
raise ArgumentError, "Spurious elements in :order! #{spurious.inspect}" unless spurious.empty?
order
end
end
end
gyoku-1.4.0/lib/gyoku/xml_key.rb 0000644 0000041 0000041 00000004357 14235144521 016615 0 ustar www-data www-data module Gyoku
module XMLKey
class << self
CAMELCASE = lambda { |key| key.gsub(/\/(.?)/) { |m| "::#{m.split('').last.upcase}" }.gsub(/(?:^|_)(.)/) { |m| m.split('').last.upcase } }
LOWER_CAMELCASE = lambda { |key| key[0].chr.downcase + CAMELCASE.call(key)[1..-1] }
UPCASE = lambda { |key| key.upcase }
FORMULAS = {
:lower_camelcase => lambda { |key| LOWER_CAMELCASE.call(key) },
:camelcase => lambda { |key| CAMELCASE.call(key) },
:upcase => lambda { |key| UPCASE.call(key) },
:none => lambda { |key| key }
}
# Converts a given +object+ with +options+ to an XML key.
def create(key, options = {})
xml_key = chop_special_characters key.to_s
if unqualified = unqualify?(xml_key)
xml_key = xml_key.split(":").last
end
xml_key = key_converter(options, xml_key).call(xml_key) if Symbol === key
if !unqualified && qualify?(options) && !xml_key.include?(":")
xml_key = "#{options[:namespace]}:#{xml_key}"
end
xml_key
end
private
# Returns the formula for converting Symbol keys.
def key_converter(options, xml_key)
return options[:key_converter] if options[:key_converter].is_a? Proc
defined_key = options[:key_to_convert]
if (defined_key != nil) && (defined_key == xml_key)
key_converter = options[:key_converter]
elsif defined_key != nil
key_converter = :lower_camelcase
elsif (options[:except] == xml_key)
key_converter = :lower_camelcase
else
key_converter = options[:key_converter] || :lower_camelcase
end
FORMULAS[key_converter]
end
# Chops special characters from the end of a given +string+.
def chop_special_characters(string)
["!", "/"].include?(string[-1, 1]) ? string.chop : string
end
# Returns whether to remove the namespace from a given +key+.
def unqualify?(key)
key[0, 1] == ":"
end
# Returns whether to namespace all keys (elementFormDefault).
def qualify?(options)
options[:element_form_default] == :qualified && options[:namespace]
end
end
end
end
gyoku-1.4.0/lib/gyoku/prettifier.rb 0000644 0000041 0000041 00000001275 14235144521 017316 0 ustar www-data www-data require 'rexml/document'
module Gyoku
class Prettifier
DEFAULT_INDENT = 2
DEFAULT_COMPACT = true
attr_accessor :indent, :compact
def self.prettify(xml, options = {})
new(options).prettify(xml)
end
def initialize(options = {})
@indent = options[:indent] || DEFAULT_INDENT
@compact = options[:compact].nil? ? DEFAULT_COMPACT : options[:compact]
end
# Adds intendations and newlines to +xml+ to make it more readable
def prettify(xml)
result = ''
formatter = REXML::Formatters::Pretty.new indent
formatter.compact = compact
doc = REXML::Document.new xml
formatter.write doc, result
result
end
end
end
gyoku-1.4.0/gyoku.gemspec 0000644 0000041 0000041 00000001443 14235144521 015410 0 ustar www-data www-data $:.push File.expand_path("../lib", __FILE__)
require "gyoku/version"
Gem::Specification.new do |s|
s.name = "gyoku"
s.version = Gyoku::VERSION
s.platform = Gem::Platform::RUBY
s.authors = "Daniel Harrington"
s.email = "me@rubiii.com"
s.homepage = "https://github.com/savonrb/#{s.name}"
s.summary = "Translates Ruby Hashes to XML"
s.description = "Gyoku translates Ruby Hashes to XML"
s.required_ruby_version = '>= 1.9.2'
s.license = "MIT"
s.add_dependency "builder", ">= 2.1.2"
s.add_dependency "rexml", "~> 3.0"
s.add_development_dependency "rake"
s.add_development_dependency "rspec"
s.files = `git ls-files`.split("\n")
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
s.require_paths = ["lib"]
end
gyoku-1.4.0/Gemfile 0000644 0000041 0000041 00000000156 14235144521 014200 0 ustar www-data www-data source 'https://rubygems.org'
gemspec
gem 'simplecov', :require => false
gem 'coveralls', :require => false
gyoku-1.4.0/.github/ 0000755 0000041 0000041 00000000000 14235144521 014243 5 ustar www-data www-data gyoku-1.4.0/.github/workflows/ 0000755 0000041 0000041 00000000000 14235144521 016300 5 ustar www-data www-data gyoku-1.4.0/.github/workflows/ci.yml 0000644 0000041 0000041 00000001121 14235144521 017411 0 ustar www-data www-data name: CI
on:
push:
branches: [ master ]
pull_request:
branches: [ master ]
jobs:
test:
runs-on: ubuntu-latest
strategy:
matrix:
ruby-version:
- 3.1
- "3.0"
- 2.7
- 2.6
steps:
- uses: actions/checkout@v3
- name: Set up Ruby ${{ matrix.ruby-version }}
uses: ruby/setup-ruby@v1
with:
ruby-version: ${{ matrix.ruby-version }}
bundler-cache: true # runs 'bundle install' and caches installed gems automatically
- name: Run tests
run: bundle exec rake
gyoku-1.4.0/MIT-LICENSE 0000644 0000041 0000041 00000002045 14235144521 014340 0 ustar www-data www-data Copyright (c) 2010 Daniel Harrington
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.