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 +4 -4
- data/README.md +93 -0
- data/lib/xmlbuilder.rb +94 -88
- data/test/all.rb +5 -0
- data/test/examples.rb +100 -0
- data/test/tags.rb +53 -0
- metadata +15 -11
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: cad808a09138b6583f6d1745180e7884f1d6a5486eaa7328cff44fc06b7e4a4d
|
4
|
+
data.tar.gz: c5522c2322483f81bd0b48f42f09849c59a9aea2c1348083164660ccb14a35a3
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: fb435fd60b53aefb8ac06e463d0768031faede54f5f297d08ed33ec5ec6722bb5a04265f390b002d2b61c16fa85dc4b24e99eaf6f7072cf5ebb9e4137a92e693
|
7
|
+
data.tar.gz: ac7a53d47591a95b8e540dac7ef008ac640e9d0d6ffd1b5c85e116afb15fb44502199628dec096a100d7e46be67cd3a4d9373991b9f8d5d34c38d6620d608a06
|
data/README.md
ADDED
@@ -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.
|
data/lib/xmlbuilder.rb
CHANGED
@@ -1,97 +1,103 @@
|
|
1
1
|
# XMLBuilder is a library that allows you to easily create XML.
|
2
|
-
#
|
3
|
-
#
|
4
|
-
#
|
5
|
-
#
|
6
|
-
#
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
#
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
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
|
-
|
33
|
-
|
20
|
+
end
|
21
|
+
|
22
|
+
# Sets the stored string to "" and the depth to 0.
|
34
23
|
def clear
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
#
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
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
|
-
|
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
|
+
#
|
data/test/all.rb
ADDED
data/test/examples.rb
ADDED
@@ -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
|
data/test/tags.rb
ADDED
@@ -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.
|
4
|
+
version: 0.4.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
|
-
-
|
7
|
+
- Coderz
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2020-10-20 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
|
-
description:
|
14
|
-
|
15
|
-
|
16
|
-
email:
|
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
|
-
|
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:
|
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:
|
49
|
+
summary: An idiomatic library allowing you to generate XML
|
46
50
|
test_files: []
|