xmlbuilder 0.2.9 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 201431a2be1bd3b983848d916c346f54f7ae346e27721c0ea5cb7d18f29fef79
4
- data.tar.gz: b8c7da4072e08df5200cd2f82c40ed5ebfe7019532869d429d573d5bfbaf024f
3
+ metadata.gz: cad808a09138b6583f6d1745180e7884f1d6a5486eaa7328cff44fc06b7e4a4d
4
+ data.tar.gz: c5522c2322483f81bd0b48f42f09849c59a9aea2c1348083164660ccb14a35a3
5
5
  SHA512:
6
- metadata.gz: 3da9c440d70230c80dee62dcb8f8a345a3788acb147d748a4b5e10fd2478cdf6ae8d4767b361a850bde5723e9fa93af84634b902c9e9430073314fd730cb3127
7
- data.tar.gz: 405d3caf5ba25426760c4b63a38c16b7f059665d33eed2a41d2466e35ce41d1baeaa5d67b2a430fff16539c2f7f62d07958a3a4ba560cd8cf12bb130ffe9fa00
6
+ metadata.gz: fb435fd60b53aefb8ac06e463d0768031faede54f5f297d08ed33ec5ec6722bb5a04265f390b002d2b61c16fa85dc4b24e99eaf6f7072cf5ebb9e4137a92e693
7
+ data.tar.gz: ac7a53d47591a95b8e540dac7ef008ac640e9d0d6ffd1b5c85e116afb15fb44502199628dec096a100d7e46be67cd3a4d9373991b9f8d5d34c38d6620d608a06
@@ -0,0 +1,93 @@
1
+ ## This is not the original XmlBuilder library.
2
+ It is a separate library that uses a different interface. I did not write the original XmlBuilder gem, whose owner yanked it from rubygems.org in 2012.
3
+
4
+
5
+ # xmlbuilder: A simple way to build XML
6
+ This library allows you to generate XML in an idiomatic, human-readable way. It's designed to be easy to use to automatically generate XML on the fly or as needed inside your terminal.
7
+
8
+ ## Examples:
9
+ A hard-coded example:
10
+ ```
11
+ xml = XMLBuilder.new
12
+ xml.document type: 'xml', use: 'example' do
13
+ xml.description "This is an example of using XMLBuilder."
14
+ xml.nextmeeting date: Time.now+100000 do
15
+ xml.agenda "Nothing of importance will be decided."
16
+ xml.clearance true, level: 'classified'
17
+ # Passing in true creates a void tag
18
+ end
19
+ end
20
+
21
+ p xml.str
22
+
23
+ # =>
24
+ <document type="xml" use="example">
25
+ <description>
26
+ This is an example of using XMLBuilder.
27
+ </description>
28
+ <nextmeeting date="2017-02-10 21:56:56 -0800">
29
+ <agenda>
30
+ Nothing of importance will be decided.
31
+ </agenda>
32
+ <clearance level="classified" />
33
+ </nextmeeting>
34
+ </document>
35
+ ```
36
+
37
+ Automatically encoding a data structure:
38
+ ```
39
+ data = [
40
+ {
41
+ title: "Assassin's Apprentice",
42
+ author: "Robin Hobb",
43
+ published: 1995,
44
+ rating: 4.5
45
+ },
46
+ {
47
+ title: "The Fifth Season",
48
+ author: "N. K. Jemisin",
49
+ published: 2015,
50
+ rating: 4.6
51
+ },
52
+ ...
53
+ ].sort_by { |book| book['rating'] }
54
+
55
+ output = XMLBuilder.new
56
+ output.collection genre: 'fantasy' do
57
+ data.each do |book|
58
+ output.book do
59
+ book.each { |field, value| output.add_element field, value }
60
+ end
61
+ end
62
+ end
63
+
64
+ p output
65
+
66
+ # =>
67
+ <collection genre="fantasy">
68
+ <book>
69
+ <title>
70
+ Assassin's Apprentice
71
+ </title>
72
+ <author>
73
+ Robin Hobb
74
+ </author>
75
+ <published>
76
+ 1995
77
+ </published>
78
+ <rating>
79
+ 4.5
80
+ </rating>
81
+ </book>
82
+ ...
83
+ </collection>
84
+ ```
85
+
86
+ ## Installation
87
+ `gem install xmlbuilder`
88
+ or add `gem 'xmlbuilder'` to your Gemfile
89
+
90
+ [Here is the gem repo](https://rubygems.org/gems/xmlbuilder)
91
+
92
+ ## License
93
+ This work is licensed under the Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License. To view a copy of this license, visit http://creativecommons.org/licenses/by-nc-sa/4.0/ or send a letter to Creative Commons, PO Box 1866, Mountain View, CA 94042, USA.
@@ -1,97 +1,103 @@
1
1
  # XMLBuilder is a library that allows you to easily create XML.
2
- # Here's an example:
3
- # xml = XMLBuilder.new
4
- # xml.document :type => 'xml', :use => 'example' do
5
- # xml.description "This is an example of using XMLBuilder.\n" # If you pass in a string, it will automatically input it into
6
- # xml.nextmeeting :date => Time.now+100000 do # the output string. You can't use a block with it, though.
7
- # xml.agenda "Nothing of importance will be decided.\n"
8
- # xml.clearance true, :level => :classified # Passing true in as the first parameter will cause it to be a standalone tag.
9
- # end
10
- # xml.add "I hope that this has been a good example."
11
- # end
12
- # p xml.str
13
- # <document type="xml" use="example">
14
- # <description>
15
- # This is an example of using XMLBuilder.
16
- # </description>
17
- # <nextmeeting date="2017-02-10 21:56:56 -0800">
18
- # <agenda>
19
- # Nothing of importance will be decided.
20
- # </agenda>
21
- # <clearance level="classified" />
22
- # </nextmeeting>
23
- # I hope that this has been a good example.
24
- # </document>
25
- class XMLBuilder
26
- attr_reader :str
27
- # #initialize simply sets the stored string to "" and the depth (used in nesting tags) to 0.
28
- def initialize(separator=" ") # separator set to two spaces by default, used in nesting
2
+ #
3
+ # Licensed under CC-BY-NC-SA-4.0
4
+ #
5
+ # Written by Coderz
6
+ #
7
+
8
+
9
+ class XMLBuilder
10
+ @@default_separator = " "
11
+ # separator set to two spaces by default, used in nesting
12
+
13
+ attr_reader :str
14
+ attr_accessor :separator
15
+
16
+ def initialize(separator=@@default_separator)
29
17
  @str = ""
30
18
  @depth = 0
31
19
  @separator = separator
32
- end
33
- # #clear does the same thing as #initialize (by delegating to it).
20
+ end
21
+
22
+ # Sets the stored string to "" and the depth to 0.
34
23
  def clear
35
- initialize # That's essentially what it does.
36
- end
37
- # #add adds a string (with no processing) to the object's string.
38
- def add(str)
39
- @str << str
40
- end
41
- def to_ary
42
- return [@str]
43
- end
44
- # #method_missing is the brains of the operation. It takes the name of the tag to add,
45
- # an optional string to put in the tag, an optional boolean parameter which signifies whether
46
- # to make it a single tag or not, any options to put in the tag, and a block to evaluate between
47
- # the opening and closing tags. There is an alias, #add_element, which is used for already defined
48
- # methods such as #send and #method_missing.
49
- def method_missing(name, *args, &block)
50
- internal = nil # Internal is a string that is put between the sides of the element
51
- if args.length == 2
52
- if args[0].is_a? String
53
- one_tag, internal, hash = false, *args
54
- else
55
- one_tag, hash = *args
56
- end
57
- elsif args.length == 1
58
- if args[0].is_a? Hash
59
- one_tag, hash = *[false, args[0]]
60
- elsif args[0].is_a? String
61
- one_tag, internal, hash = false, args[0], {}
62
- else
63
- one_tag, hash = *[args[0], {}]
64
- end
65
- else
66
- one_tag, hash = false, {}
67
- end
68
- @str << @separator.to_s * @depth
69
- @str << "<#{name}"
70
- if one_tag
71
- hash.each do |k, v|
72
- @str << " #{k}=\"#{v}\""
73
- end
74
- @str << " />\n"
75
- else
76
- hash.each do |k, v|
77
- @str << " #{k}=\"#{v}\""
78
- end
79
- @str << ">\n"
80
- if !internal.nil?
81
- @str << internal.to_str + "\n"
82
- elsif block
83
- @depth += 1
84
- block.call
85
- @depth -= 1
86
- end
87
- @str << @separator * @depth
88
- @str << "</#{name}>\n"
89
- end
90
- return @str
91
- end
92
- alias :add_element :method_missing
24
+ initialize(@separator)
25
+ self
26
+ end
27
+
28
+ # Adds a string (with no preprocessing) to the object's string.
29
+ def add(*strs)
30
+ @str << strs.flatten.join('')
31
+ end
32
+
33
+ # Takes the name of the tag to add, an optional string to put in the tag, an optional boolean parameter which signifies whether to make it a single tag or not, any options to put in the tag, and a block to evaluate between the opening and closing tags. Aliased to #method_missing to allow dynamic tag creation.
34
+ def add_element(name, *args)
35
+ one_tag, internal, attrs = process_args args
36
+
37
+ # logic time
38
+ add indentation, ?<, name
39
+ attrs.each do |attr, value|
40
+ add " #{attr}=\"#{value}\""
41
+ end
42
+ if one_tag
43
+ add " />\n"
44
+ return self
45
+ else
46
+ add ?>
47
+ end
48
+ if internal
49
+ add internal
50
+ elsif block_given?
51
+ @depth += 1
52
+ add "\n"
53
+ yield
54
+ @depth -= 1
55
+ end
56
+ add indentation unless internal
57
+ add "</#{name}>\n"
58
+ return self
59
+ end
60
+
61
+ def process_args(args)
62
+ # Argument cheat sheet:
63
+ # <name hash[0]="hash[1]">
64
+ # internal
65
+ # </name>
66
+
67
+ internal = nil
68
+ if args.size == 2
69
+ if args[0] == !!args[0]
70
+ one_tag, hash = *args
71
+ else
72
+ one_tag, internal, hash = false, *args
73
+ end
74
+ elsif args.size == 1
75
+ if args[0].is_a? Hash
76
+ one_tag, hash = *[false, args[0]]
77
+ elsif args[0] == !!args[0]
78
+ one_tag, hash = args[0], {}
79
+ else
80
+ one_tag, internal, hash = false, args[0].to_s, {}
81
+ end
82
+ else
83
+ one_tag, hash = false, {}
84
+ end
85
+ return one_tag, internal, hash
86
+ end
87
+ def indentation; @separator * @depth; end
88
+ alias :method_missing :add_element
93
89
  alias :to_s :str
94
90
  alias :to_str :str
95
- alias :inspect :str
91
+ alias :inspect :str
92
+ private :process_args, :indentation
96
93
  public :add_element
97
94
  end
95
+
96
+ #
97
+ # This work is licensed under the Creative Commons
98
+ # Attribution-NonCommercial-ShareAlike 4.0 International License.
99
+ # To view a copy of this license, visit
100
+ # http://creativecommons.org/licenses/by-nc-sa/4.0/ or
101
+ # send a letter to
102
+ # Creative Commons, PO Box 1866, Mountain View, CA 94042, USA.
103
+ #
@@ -0,0 +1,5 @@
1
+ # haha testing go brrr
2
+
3
+ require 'minitest/autorun'
4
+ require_relative 'tags'
5
+ require_relative 'examples'
@@ -0,0 +1,100 @@
1
+ require_relative '../lib/xmlbuilder'
2
+
3
+ # This test file contains various HTML snippets and fragments
4
+ # in order to "stress-test" the library. Also I can't think of
5
+ # edge cases so hopefully this will find them.
6
+
7
+ $expected = [] # array of strings
8
+ $actual = [] # array of procs
9
+
10
+ $expected << <<-end
11
+ <html>
12
+ <head>
13
+ <title>Page Title</title>
14
+ </head>
15
+ <body>
16
+ <h1>My First Heading</h1>
17
+ <p>My first paragraph.</p>
18
+ </body>
19
+ </html>
20
+ end
21
+
22
+ $actual << Proc.new do |xml|
23
+ xml.html do
24
+ xml.head do
25
+ xml.title 'Page Title'
26
+ end
27
+ xml.body do
28
+ xml.h1 'My First Heading'
29
+ xml.p 'My first paragraph.'
30
+ end
31
+ end
32
+ end
33
+
34
+ $expected << <<-end
35
+ <note>
36
+ <to>Dave</to>
37
+ <from>The Empress of Death</from>
38
+ <heading>Reminder</heading>
39
+ <body>Don't forget me this weekend!</body>
40
+ </note>
41
+ end
42
+
43
+ $actual << Proc.new do |xml|
44
+ xml.note do
45
+ xml.to 'Dave'
46
+ xml.from 'The Empress of Death'
47
+ xml.heading 'Reminder'
48
+ xml.body 'Don\'t forget me this weekend!'
49
+ end
50
+ end
51
+
52
+ $expected << <<-end
53
+ <bookstore>
54
+ <book category="COOKING">
55
+ <title lang="en">Everyday Italian</title>
56
+ <author>Giada De Laurentiis</author>
57
+ <year>2005</year>
58
+ <price>30.00</price>
59
+ </book>
60
+ <book category="CHILDREN">
61
+ <title lang="en">Harry Potter</title>
62
+ <author>J K. Rowling</author>
63
+ <year>2005</year>
64
+ <price>29.99</price>
65
+ </book>
66
+ </bookstore>
67
+ end
68
+
69
+ $actual << Proc.new do |xml|
70
+ xml.bookstore do
71
+ xml.book category: 'COOKING' do
72
+ xml.title 'Everyday Italian', lang: 'en'
73
+ xml.author 'Giada De Laurentiis'
74
+ xml.year '2005'
75
+ xml.price '30.00'
76
+ end
77
+ xml.book category: 'CHILDREN' do
78
+ xml.title 'Harry Potter', lang: 'en'
79
+ xml.author 'J K. Rowling'
80
+ xml.year '2005'
81
+ xml.price '29.99'
82
+ end
83
+ end
84
+ end
85
+
86
+
87
+
88
+ class XMLBuilderStressTest < Minitest::Test
89
+ @@cases = $expected.zip($actual)
90
+ def setup
91
+ @test_obj = XMLBuilder.new
92
+ end
93
+ def test_all_cases
94
+ @@cases.each do |expected, actual|
95
+ actual = actual[@test_obj]
96
+ assert_equal expected.to_s, actual.to_s
97
+ @test_obj.clear
98
+ end
99
+ end
100
+ end
@@ -0,0 +1,53 @@
1
+ require_relative '../lib/xmlbuilder'
2
+
3
+ class XMLBuilderTagTest < Minitest::Test
4
+ def setup
5
+ @test_obj = XMLBuilder.new
6
+ end
7
+
8
+ def test_builder_can_create_tags
9
+ @test_obj.add_element 'test_tag'
10
+ assert_equal '<test_tag></test_tag>', @test_obj.to_s.chomp
11
+ @test_obj.clear.add_element 'test_tag', true # Void element
12
+ assert_equal '<test_tag />', @test_obj.to_s.chomp
13
+ end
14
+
15
+ def test_builder_can_create_attributes
16
+ @test_obj.add_element 'test', attr: 'value'
17
+ assert_equal '<test attr="value"></test>', @test_obj.to_s.chomp
18
+ end
19
+
20
+ def test_can_handle_non_string_attrs_and_contents
21
+ @test_obj.add_element 'test', true, num: 37
22
+ assert_equal '<test num="37" />', @test_obj.to_s.chomp
23
+ @test_obj.clear.add_element 'test', 54
24
+ assert_equal "<test>54</test>", @test_obj.to_s.chomp
25
+ end
26
+
27
+ # May move to 'test/examples.rb'
28
+ def test_builder_can_nest_elements_correctly
29
+ expected = <<~end
30
+ <html>
31
+ <head>
32
+ <title>Test Title</title>
33
+ </head>
34
+ <body>
35
+ <p class="content">This is a piece of test content.</p>
36
+ <br />
37
+ </body>
38
+ </html>
39
+ end
40
+
41
+ xml = @test_obj
42
+ xml.html do
43
+ xml.head do
44
+ xml.title 'Test Title'
45
+ end
46
+ xml.body do
47
+ xml.p 'This is a piece of test content.', 'class': 'content'
48
+ xml.br true
49
+ end
50
+ end
51
+ assert_equal expected, xml.str
52
+ end
53
+ end
metadata CHANGED
@@ -1,25 +1,29 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: xmlbuilder
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.9
4
+ version: 0.4.0
5
5
  platform: ruby
6
6
  authors:
7
- - Coderzthereal
7
+ - Coderz
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-12-04 00:00:00.000000000 Z
11
+ date: 2020-10-20 00:00:00.000000000 Z
12
12
  dependencies: []
13
- description: |-
14
- This gem allows you to write XML in a very Ruby-ish way. It supports
15
- single tags, nesting tags, and adding strings. With a recent update, it also supports indentation.
16
- email: coderzthegamer@gmail.com
13
+ description: This library allows you to generate XML in an idiomatic, human-readable
14
+ way. It's designed to be easy to use to automatically generate XML on the fly or
15
+ as needed inside your terminal.
16
+ email:
17
17
  executables: []
18
18
  extensions: []
19
19
  extra_rdoc_files: []
20
20
  files:
21
- - lib/xmlbuilder.rb
22
- homepage: https://github.com/Coderzthereal/xmlbuilder
21
+ - "./lib/xmlbuilder.rb"
22
+ - "./test/all.rb"
23
+ - "./test/examples.rb"
24
+ - "./test/tags.rb"
25
+ - README.md
26
+ homepage: https://rubygems.org/gems/xmlbuilder
23
27
  licenses:
24
28
  - CC-BY-NC-SA-4.0
25
29
  metadata: {}
@@ -31,7 +35,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
31
35
  requirements:
32
36
  - - ">="
33
37
  - !ruby/object:Gem::Version
34
- version: 1.9.2
38
+ version: 2.3.0
35
39
  required_rubygems_version: !ruby/object:Gem::Requirement
36
40
  requirements:
37
41
  - - ">="
@@ -42,5 +46,5 @@ rubyforge_project:
42
46
  rubygems_version: 2.7.6
43
47
  signing_key:
44
48
  specification_version: 4
45
- summary: A simple gem that allows you to write XML in a very Ruby-ish way.
49
+ summary: An idiomatic library allowing you to generate XML
46
50
  test_files: []