clifton_lib 0.0.1
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.
- data/.gitignore +35 -0
- data/Gemfile +4 -0
- data/Gemfile.lock +17 -0
- data/LICENSE +21 -0
- data/LICENSE.txt +22 -0
- data/README.md +119 -0
- data/Rakefile +1 -0
- data/clifton_lib.gemspec +23 -0
- data/lib/clifton_lib.rb +17 -0
- data/lib/clifton_lib/version.rb +3 -0
- data/lib/clifton_lib/xml/xml_attribute.rb +19 -0
- data/lib/clifton_lib/xml/xml_declaration_node.rb +16 -0
- data/lib/clifton_lib/xml/xml_document.rb +136 -0
- data/lib/clifton_lib/xml/xml_element.rb +32 -0
- data/lib/clifton_lib/xml/xml_node.rb +35 -0
- data/lib/clifton_lib/xml/xml_text_writer.rb +55 -0
- data/test/xml_document_tests.rb +109 -0
- metadata +87 -0
data/.gitignore
ADDED
@@ -0,0 +1,35 @@
|
|
1
|
+
*.gem
|
2
|
+
*.rbc
|
3
|
+
/.config
|
4
|
+
/coverage/
|
5
|
+
/InstalledFiles
|
6
|
+
/pkg/
|
7
|
+
/spec/reports/
|
8
|
+
/test/tmp/
|
9
|
+
/test/version_tmp/
|
10
|
+
/tmp/
|
11
|
+
|
12
|
+
## Specific to RubyMotion:
|
13
|
+
.dat*
|
14
|
+
.repl_history
|
15
|
+
build/
|
16
|
+
|
17
|
+
## Documentation cache and generated files:
|
18
|
+
/.yardoc/
|
19
|
+
/_yardoc/
|
20
|
+
/doc/
|
21
|
+
/rdoc/
|
22
|
+
|
23
|
+
## Environment normalisation:
|
24
|
+
/.bundle/
|
25
|
+
/lib/bundler/man/
|
26
|
+
|
27
|
+
# for a library or gem, you might want to ignore these files since the code is
|
28
|
+
# intended to run in multiple environments; otherwise, check them in:
|
29
|
+
# Gemfile.lock
|
30
|
+
# .ruby-version
|
31
|
+
# .ruby-gemset
|
32
|
+
|
33
|
+
# unless supporting rvm < 1.11.0 or doing something fancy, ignore this:
|
34
|
+
.rvmrc
|
35
|
+
.idea
|
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2014 Marc Clifton
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
13
|
+
copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
21
|
+
SOFTWARE.
|
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2014 Marc Clifton
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,119 @@
|
|
1
|
+
# CliftonLib
|
2
|
+
|
3
|
+
This is a collection of useful functionality that I require for various projects that I'm working on.
|
4
|
+
|
5
|
+
In version 0.0.1, I've implemented several XML helper classes, similar to .NET's XmlDocument, to facilitate the
|
6
|
+
creation and serialization of XML. In this version, the support is bare bones but sufficient for what I need done.
|
7
|
+
|
8
|
+
Why do this?
|
9
|
+
|
10
|
+
All the implementations for XML support that I've seen in Ruby utilize the "method missing" feature, so that markup is written in a DSL manner. For example:
|
11
|
+
|
12
|
+
doc.product = 'Apples'
|
13
|
+
|
14
|
+
will yield something like:
|
15
|
+
|
16
|
+
<product>Apples</product>
|
17
|
+
|
18
|
+
I have several issues with this:
|
19
|
+
|
20
|
+
1. It isn't object oriented.
|
21
|
+
2. It assumes you know the element and attribute names, which isn't convenient when generating XML dynamically from other data sources
|
22
|
+
3. It leverages "method missing", which affects performance and creates an internal DSL which isn't necessary.
|
23
|
+
4. Frequently, the parameters are passed as hashes, which I find particularly evil in Ruby as they don't document what the valid parameter-hashes are via function parameters.
|
24
|
+
|
25
|
+
Instead, I want to base XML document generation (and eventually parsing) on Microsoft's implementation of the XmlDocument class in .NET:
|
26
|
+
|
27
|
+
http://msdn.microsoft.com/en-us/library/system.xml.xmldocument.aspx
|
28
|
+
|
29
|
+
This implementation:
|
30
|
+
|
31
|
+
1. Is a decent object-oriented solution for creating XML documents
|
32
|
+
2. Inherently supports dynamic XML generation
|
33
|
+
3. Isn't DSL-ish.
|
34
|
+
|
35
|
+
## A note about the code
|
36
|
+
|
37
|
+
You'll find that I do certain things, like explicitly return nil when the function isn't intended to return anything. This avoids accidental usage of a return from a function where
|
38
|
+
that is an unintended consequence of the last line executed in the function.
|
39
|
+
|
40
|
+
## Installation
|
41
|
+
|
42
|
+
Add this line to your application's Gemfile:
|
43
|
+
|
44
|
+
gem 'clifton_lib'
|
45
|
+
|
46
|
+
And then execute:
|
47
|
+
|
48
|
+
$ bundle
|
49
|
+
|
50
|
+
Or install it yourself as:
|
51
|
+
|
52
|
+
$ gem install clifton_lib
|
53
|
+
|
54
|
+
## Usage
|
55
|
+
|
56
|
+
XML Serialization Example:
|
57
|
+
|
58
|
+
```ruby
|
59
|
+
require 'test/unit'
|
60
|
+
require 'clifton_lib/xml/xml_document'
|
61
|
+
require 'clifton_lib/xml/xml_declaration_node'
|
62
|
+
require 'clifton_lib/xml/xml_text_writer'
|
63
|
+
|
64
|
+
include CliftonXml
|
65
|
+
|
66
|
+
def test_serialization
|
67
|
+
xdoc = XmlDocument.new()
|
68
|
+
decl_node = xdoc.create_xml_declaration('1.0', 'UTF-8')
|
69
|
+
xdoc.append_child(decl_node)
|
70
|
+
|
71
|
+
products = xdoc.create_element('Products')
|
72
|
+
xdoc.append_child(products)
|
73
|
+
|
74
|
+
product1 = xdoc.create_element('Product')
|
75
|
+
id_attr1 = xdoc.create_attribute('ID')
|
76
|
+
name_attr1 = xdoc.create_attribute('Name')
|
77
|
+
id_attr1.value = '1'
|
78
|
+
name_attr1.value = 'Apples'
|
79
|
+
product1.append_attribute(id_attr1)
|
80
|
+
product1.append_attribute(name_attr1)
|
81
|
+
product1.inner_text = 'foobar'
|
82
|
+
|
83
|
+
product2 = xdoc.create_element('Product')
|
84
|
+
id_attr2 = xdoc.create_attribute('ID')
|
85
|
+
name_attr2 = xdoc.create_attribute('Name')
|
86
|
+
id_attr2.value = '2'
|
87
|
+
name_attr2.value = 'Oranges'
|
88
|
+
product2.append_attribute(id_attr2)
|
89
|
+
product2.append_attribute(name_attr2)
|
90
|
+
|
91
|
+
products.append_child(product1)
|
92
|
+
products.append_child(product2)
|
93
|
+
|
94
|
+
tw = XmlTextWriter.new()
|
95
|
+
tw.formatting = :indented
|
96
|
+
xdoc.save(tw)
|
97
|
+
output = tw.output
|
98
|
+
assert_equal %Q|<?xml version="1.0" encoding="UTF-8"?>\r\n<Products>\r\n <Product ID="1" Name="Apples">foobar</Product>\r\n <Product ID="2" Name="Oranges"/>\r\n</Products>|, output
|
99
|
+
end
|
100
|
+
```
|
101
|
+
|
102
|
+
The result looks like:
|
103
|
+
|
104
|
+
```XML
|
105
|
+
<Products>
|
106
|
+
<Product ID="1" Name="Apples">foobar</Product>
|
107
|
+
<Product ID="2" Name="Oranges" />
|
108
|
+
</Products>
|
109
|
+
```
|
110
|
+
|
111
|
+
For further examples, see the xml_document_tests.rb file.
|
112
|
+
|
113
|
+
## Contributing
|
114
|
+
|
115
|
+
1. Fork it
|
116
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
117
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
118
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
119
|
+
5. Create new Pull Request
|
data/Rakefile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
data/clifton_lib.gemspec
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'clifton_lib/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "clifton_lib"
|
8
|
+
spec.version = CliftonLib::VERSION
|
9
|
+
spec.authors = ["Marc Clifton"]
|
10
|
+
spec.email = ["marc.clifton@gmail.com"]
|
11
|
+
spec.description = %q{A collection of useful helper classes, initially a set of classes to support creation and serialization of XML.}
|
12
|
+
spec.summary = %q{Collection of useful helper classes.}
|
13
|
+
spec.homepage = "https://github.com/cliftonm/clifton_lib"
|
14
|
+
spec.license = "MIT"
|
15
|
+
|
16
|
+
spec.files = `git ls-files`.split($/)
|
17
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
|
+
spec.require_paths = ["lib"]
|
20
|
+
|
21
|
+
spec.add_development_dependency "bundler", "~> 1.3"
|
22
|
+
spec.add_development_dependency "rake"
|
23
|
+
end
|
data/lib/clifton_lib.rb
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
require "clifton_lib/version"
|
2
|
+
|
3
|
+
module CliftonXml
|
4
|
+
class XmlAttribute
|
5
|
+
attr_accessor :name
|
6
|
+
attr_accessor :value
|
7
|
+
|
8
|
+
# XmlAttribute.new() {@name = [name]; @value = [value]}
|
9
|
+
def initialize(&block)
|
10
|
+
# this can use the form {@<attr> = <value>}
|
11
|
+
# allow for default constructor.
|
12
|
+
instance_eval(&block) unless block.nil?
|
13
|
+
# yield self if block_given?
|
14
|
+
# this requires the form {|inst| inst.<attr> = <value>}
|
15
|
+
|
16
|
+
self
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
require "clifton_lib/version"
|
2
|
+
require "clifton_lib/xml/xml_attribute"
|
3
|
+
require "clifton_lib/xml/xml_node"
|
4
|
+
|
5
|
+
module CliftonXml
|
6
|
+
class XmlDeclarationNode < XmlNode
|
7
|
+
|
8
|
+
# XmlDeclarationNode.new() {... attribute initialization ... }
|
9
|
+
def initialize(&block)
|
10
|
+
super()
|
11
|
+
instance_eval(&block) unless block.nil?
|
12
|
+
|
13
|
+
self
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,136 @@
|
|
1
|
+
require "clifton_lib/version"
|
2
|
+
require "clifton_lib/xml/xml_attribute"
|
3
|
+
require "clifton_lib/xml/xml_element"
|
4
|
+
require "clifton_lib/xml/xml_node"
|
5
|
+
require "clifton_lib/xml/xml_declaration_node"
|
6
|
+
|
7
|
+
module CliftonXml
|
8
|
+
class XmlDocument < XmlNode
|
9
|
+
|
10
|
+
# XmlDocument.new()
|
11
|
+
def initialize
|
12
|
+
super()
|
13
|
+
end
|
14
|
+
|
15
|
+
# XmlDeclarationNode create_xml_declaration(string version, string encoding)
|
16
|
+
def create_xml_declaration(version, encoding)
|
17
|
+
declNode = XmlDeclarationNode.new() {
|
18
|
+
@attributes << XmlAttribute.new() {@name='version'; @value=version}
|
19
|
+
@attributes << XmlAttribute.new() {@name='encoding'; @value=encoding}
|
20
|
+
}
|
21
|
+
|
22
|
+
declNode
|
23
|
+
end
|
24
|
+
|
25
|
+
# XmlAttribute create_attribute(string name)
|
26
|
+
def create_attribute(name)
|
27
|
+
attr = XmlAttribute.new() {@name = name}
|
28
|
+
|
29
|
+
attr
|
30
|
+
end
|
31
|
+
|
32
|
+
# XmlElement create_element(string name)
|
33
|
+
def create_element(name)
|
34
|
+
elem = XmlElement.new() {@name = name}
|
35
|
+
|
36
|
+
elem
|
37
|
+
end
|
38
|
+
|
39
|
+
def document_element()
|
40
|
+
# TODO
|
41
|
+
end
|
42
|
+
|
43
|
+
def document_type()
|
44
|
+
# TODO
|
45
|
+
end
|
46
|
+
|
47
|
+
# void save(XmlTextWriter writer)
|
48
|
+
def save(writer)
|
49
|
+
write_nodes(writer, @child_nodes)
|
50
|
+
|
51
|
+
nil
|
52
|
+
end
|
53
|
+
|
54
|
+
private
|
55
|
+
|
56
|
+
# void write_nodes(XmlTextWriter writer, XmlNodes[] nodes)
|
57
|
+
def write_nodes(writer, nodes)
|
58
|
+
nodes.each_with_index do |node, idx|
|
59
|
+
# write xml declaration if it exists.
|
60
|
+
# TODO: Should throw somewhere if this isn't the first node.
|
61
|
+
if node.is_a?(XmlDeclarationNode)
|
62
|
+
writer.write('<?xml')
|
63
|
+
write_attributes(writer, node)
|
64
|
+
writer.write('?>')
|
65
|
+
writer.new_line()
|
66
|
+
else
|
67
|
+
# begin element tag and attributes
|
68
|
+
writer.write('<' + node.name)
|
69
|
+
write_attributes(writer, node)
|
70
|
+
|
71
|
+
# if inner text, write it out now.
|
72
|
+
if node.inner_text
|
73
|
+
writer.write('>' + node.inner_text)
|
74
|
+
writer.write('</' + node.name + '>')
|
75
|
+
crlf_if_more_nodes(writer, nodes, idx)
|
76
|
+
else
|
77
|
+
# Children are allowed only if there is no inner text.
|
78
|
+
if node.has_child_nodes()
|
79
|
+
# close element tag, indent, and recurse.
|
80
|
+
writer.write('>')
|
81
|
+
writer.indent()
|
82
|
+
writer.new_line()
|
83
|
+
write_nodes(writer, node.child_nodes)
|
84
|
+
writer.outdent()
|
85
|
+
writer.new_line()
|
86
|
+
# close the element
|
87
|
+
writer.write('</' + node.name + '>')
|
88
|
+
crlf_if_more_nodes(writer, nodes, idx)
|
89
|
+
else
|
90
|
+
# if no children and no inner text, use the abbreviated closing tag token.
|
91
|
+
writer.write('/>')
|
92
|
+
crlf_if_more_nodes(writer, nodes, idx)
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
nil
|
99
|
+
end
|
100
|
+
|
101
|
+
# Write the attribute collection for a node.
|
102
|
+
# void write_attributes(XmlTextWriter writer, XmlNode node)
|
103
|
+
def write_attributes(writer, node)
|
104
|
+
if node.attributes.count > 0
|
105
|
+
# stuff them into an array of strings
|
106
|
+
attrs = []
|
107
|
+
|
108
|
+
node.attributes.each do |attr|
|
109
|
+
attrs << attr.name + '="' + attr.value + '"'
|
110
|
+
end
|
111
|
+
|
112
|
+
# separate them with a space
|
113
|
+
attr_str = attrs.join(' ')
|
114
|
+
|
115
|
+
# requires a leading space as well to separate from the element name.
|
116
|
+
writer.write(' ' + attr_str)
|
117
|
+
end
|
118
|
+
|
119
|
+
nil
|
120
|
+
end
|
121
|
+
|
122
|
+
# bool more_nodes(XmlNodes[] nodes, int idx)
|
123
|
+
def more_nodes(nodes, idx)
|
124
|
+
idx + 1 < nodes.count
|
125
|
+
end
|
126
|
+
|
127
|
+
# void crlf_if_more_nodes(XmlTextWriter writer, XmlNodes[] nodes, int idx)
|
128
|
+
def crlf_if_more_nodes(writer, nodes, idx)
|
129
|
+
if more_nodes(nodes, idx)
|
130
|
+
writer.new_line()
|
131
|
+
end
|
132
|
+
|
133
|
+
nil
|
134
|
+
end
|
135
|
+
end
|
136
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
require "clifton_lib/version"
|
2
|
+
require "clifton_lib/xml/xml_node"
|
3
|
+
|
4
|
+
module CliftonXml
|
5
|
+
class XmlElement < XmlNode
|
6
|
+
|
7
|
+
# XmlElement.new()
|
8
|
+
def initialize(&block)
|
9
|
+
super()
|
10
|
+
instance_eval(&block) unless block.nil?
|
11
|
+
|
12
|
+
self
|
13
|
+
end
|
14
|
+
|
15
|
+
# void append_attributes(XmlAttribute attr)
|
16
|
+
def append_attribute(attr)
|
17
|
+
@attributes << attr
|
18
|
+
|
19
|
+
nil
|
20
|
+
end
|
21
|
+
|
22
|
+
# XmlElement previous_sibling()
|
23
|
+
def previous_sibling()
|
24
|
+
# TODO
|
25
|
+
end
|
26
|
+
|
27
|
+
# XmlElement next_sibling()
|
28
|
+
def next_sibling()
|
29
|
+
# TODO
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
require "clifton_lib/version"
|
2
|
+
|
3
|
+
module CliftonXml
|
4
|
+
class XmlNode
|
5
|
+
attr_accessor :name
|
6
|
+
attr_accessor :inner_text
|
7
|
+
attr_accessor :parent_node # Annoying rubyism -- if in the class itself, property must be read/writeable.
|
8
|
+
attr_reader :attributes
|
9
|
+
attr_reader :child_nodes
|
10
|
+
|
11
|
+
# XmlNode.new()
|
12
|
+
def initialize()
|
13
|
+
@attributes = []
|
14
|
+
@child_nodes = []
|
15
|
+
@parent_node = nil
|
16
|
+
@name = nil
|
17
|
+
@inner_text = nil
|
18
|
+
|
19
|
+
self
|
20
|
+
end
|
21
|
+
|
22
|
+
# bool has_child_nodes()
|
23
|
+
def has_child_nodes()
|
24
|
+
@child_nodes.count > 0
|
25
|
+
end
|
26
|
+
|
27
|
+
# void append_child(XmlNode node)
|
28
|
+
def append_child(node)
|
29
|
+
@child_nodes << node
|
30
|
+
node.parent_node = self
|
31
|
+
|
32
|
+
nil
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
require "clifton_lib/version"
|
2
|
+
|
3
|
+
module CliftonXml
|
4
|
+
# For the moment, simply builds a string locally.
|
5
|
+
# TODO: Implement streams, passing in an output stream to the constructor, like a StringWriter or FileWriter stream.
|
6
|
+
class XmlTextWriter
|
7
|
+
attr_accessor :formatting
|
8
|
+
attr_reader :output
|
9
|
+
|
10
|
+
# XmlTextWriter.new()
|
11
|
+
def initialize()
|
12
|
+
@output = ''
|
13
|
+
@indent = 0
|
14
|
+
@formatting = :none
|
15
|
+
end
|
16
|
+
|
17
|
+
# void write(string str)
|
18
|
+
def write(str)
|
19
|
+
@output << str
|
20
|
+
|
21
|
+
nil
|
22
|
+
end
|
23
|
+
|
24
|
+
# void new_line()
|
25
|
+
def new_line()
|
26
|
+
if @formatting == :indented
|
27
|
+
@output << "\r\n"
|
28
|
+
@output << indentation(@indent)
|
29
|
+
end
|
30
|
+
|
31
|
+
nil
|
32
|
+
end
|
33
|
+
|
34
|
+
# void indent()
|
35
|
+
def indent()
|
36
|
+
@indent = @indent + 2
|
37
|
+
|
38
|
+
nil
|
39
|
+
end
|
40
|
+
|
41
|
+
# void outdent()
|
42
|
+
def outdent()
|
43
|
+
@indent = @indent - 2
|
44
|
+
|
45
|
+
nil
|
46
|
+
end
|
47
|
+
|
48
|
+
private
|
49
|
+
|
50
|
+
# string indentation(int amt)
|
51
|
+
def indentation(amt)
|
52
|
+
' ' * amt
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
@@ -0,0 +1,109 @@
|
|
1
|
+
require 'test/unit'
|
2
|
+
require 'clifton_lib/xml/xml_document'
|
3
|
+
require 'clifton_lib/xml/xml_declaration_node'
|
4
|
+
require 'clifton_lib/xml/xml_text_writer'
|
5
|
+
|
6
|
+
include CliftonXml
|
7
|
+
|
8
|
+
class XmlDocumentTests < Test::Unit::TestCase
|
9
|
+
# Create a document and verify that no child nodes and attributes exist.
|
10
|
+
def test_create_node
|
11
|
+
xdoc = XmlDocument.new()
|
12
|
+
assert_equal xdoc.child_nodes.count, 0
|
13
|
+
assert_equal xdoc.attributes.count, 0
|
14
|
+
end
|
15
|
+
|
16
|
+
# Create an XML declaration header and verify the attribute and node counts.
|
17
|
+
def test_xml_declaration
|
18
|
+
xdoc = XmlDocument.new()
|
19
|
+
node = xdoc.create_xml_declaration('1.0', 'UTF-8')
|
20
|
+
assert_equal node.attributes.count, 2
|
21
|
+
xdoc.append_child(node)
|
22
|
+
assert_equal xdoc.child_nodes.count, 1
|
23
|
+
assert_equal xdoc.attributes.count, 0
|
24
|
+
end
|
25
|
+
|
26
|
+
# Create a document with one root and two children.
|
27
|
+
def test_element_creation
|
28
|
+
xdoc = XmlDocument.new()
|
29
|
+
products = xdoc.create_element('Products')
|
30
|
+
xdoc.append_child(products)
|
31
|
+
|
32
|
+
product1 = xdoc.create_element('Product')
|
33
|
+
product2 = xdoc.create_element('Product')
|
34
|
+
|
35
|
+
products.append_child(product1)
|
36
|
+
products.append_child(product2)
|
37
|
+
|
38
|
+
assert_equal xdoc.child_nodes.count, 1
|
39
|
+
assert_equal xdoc.child_nodes[0].child_nodes.count, 2
|
40
|
+
end
|
41
|
+
|
42
|
+
# Create a document with one root, two children, and two attributes for each child.
|
43
|
+
def test_element_attributes
|
44
|
+
xdoc = XmlDocument.new()
|
45
|
+
products = xdoc.create_element('Products')
|
46
|
+
xdoc.append_child(products)
|
47
|
+
|
48
|
+
product1 = xdoc.create_element('Product')
|
49
|
+
id_attr1 = xdoc.create_attribute('ID')
|
50
|
+
name_attr1 = xdoc.create_attribute('Name')
|
51
|
+
id_attr1.value = '1'
|
52
|
+
name_attr1.value = 'Apples'
|
53
|
+
product1.append_attribute(id_attr1)
|
54
|
+
product1.append_attribute(name_attr1)
|
55
|
+
|
56
|
+
product2 = xdoc.create_element('Product')
|
57
|
+
id_attr2 = xdoc.create_attribute('ID')
|
58
|
+
name_attr2 = xdoc.create_attribute('Name')
|
59
|
+
id_attr2.value = '2'
|
60
|
+
name_attr2.value = 'Oranges'
|
61
|
+
product2.append_attribute(id_attr1)
|
62
|
+
product2.append_attribute(name_attr1)
|
63
|
+
|
64
|
+
products.append_child(product1)
|
65
|
+
products.append_child(product2)
|
66
|
+
|
67
|
+
assert_equal xdoc.child_nodes.count, 1
|
68
|
+
assert_equal xdoc.child_nodes[0].child_nodes.count, 2
|
69
|
+
assert_equal xdoc.child_nodes[0].child_nodes[0].attributes.count, 2
|
70
|
+
assert_equal xdoc.child_nodes[0].child_nodes[1].attributes.count, 2
|
71
|
+
end
|
72
|
+
|
73
|
+
# test the serialization of a simple structure with an inner element having inner text.
|
74
|
+
def test_serialization
|
75
|
+
xdoc = XmlDocument.new()
|
76
|
+
decl_node = xdoc.create_xml_declaration('1.0', 'UTF-8')
|
77
|
+
xdoc.append_child(decl_node)
|
78
|
+
|
79
|
+
products = xdoc.create_element('Products')
|
80
|
+
xdoc.append_child(products)
|
81
|
+
|
82
|
+
product1 = xdoc.create_element('Product')
|
83
|
+
id_attr1 = xdoc.create_attribute('ID')
|
84
|
+
name_attr1 = xdoc.create_attribute('Name')
|
85
|
+
id_attr1.value = '1'
|
86
|
+
name_attr1.value = 'Apples'
|
87
|
+
product1.append_attribute(id_attr1)
|
88
|
+
product1.append_attribute(name_attr1)
|
89
|
+
product1.inner_text = 'foobar'
|
90
|
+
|
91
|
+
product2 = xdoc.create_element('Product')
|
92
|
+
id_attr2 = xdoc.create_attribute('ID')
|
93
|
+
name_attr2 = xdoc.create_attribute('Name')
|
94
|
+
id_attr2.value = '2'
|
95
|
+
name_attr2.value = 'Oranges'
|
96
|
+
product2.append_attribute(id_attr2)
|
97
|
+
product2.append_attribute(name_attr2)
|
98
|
+
|
99
|
+
products.append_child(product1)
|
100
|
+
products.append_child(product2)
|
101
|
+
|
102
|
+
tw = XmlTextWriter.new()
|
103
|
+
tw.formatting = :indented
|
104
|
+
xdoc.save(tw)
|
105
|
+
output = tw.output
|
106
|
+
assert_equal %Q|<?xml version="1.0" encoding="UTF-8"?>\r\n<Products>\r\n <Product ID="1" Name="Apples">foobar</Product>\r\n <Product ID="2" Name="Oranges"/>\r\n</Products>|, output
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
metadata
ADDED
@@ -0,0 +1,87 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: clifton_lib
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Marc Clifton
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2014-04-13 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: bundler
|
16
|
+
requirement: &26145264 !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ~>
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '1.3'
|
22
|
+
type: :development
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: *26145264
|
25
|
+
- !ruby/object:Gem::Dependency
|
26
|
+
name: rake
|
27
|
+
requirement: &26144784 !ruby/object:Gem::Requirement
|
28
|
+
none: false
|
29
|
+
requirements:
|
30
|
+
- - ! '>='
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: '0'
|
33
|
+
type: :development
|
34
|
+
prerelease: false
|
35
|
+
version_requirements: *26144784
|
36
|
+
description: A collection of useful helper classes, initially a set of classes to
|
37
|
+
support creation and serialization of XML.
|
38
|
+
email:
|
39
|
+
- marc.clifton@gmail.com
|
40
|
+
executables: []
|
41
|
+
extensions: []
|
42
|
+
extra_rdoc_files: []
|
43
|
+
files:
|
44
|
+
- .gitignore
|
45
|
+
- Gemfile
|
46
|
+
- Gemfile.lock
|
47
|
+
- LICENSE
|
48
|
+
- LICENSE.txt
|
49
|
+
- README.md
|
50
|
+
- Rakefile
|
51
|
+
- clifton_lib.gemspec
|
52
|
+
- lib/clifton_lib.rb
|
53
|
+
- lib/clifton_lib/version.rb
|
54
|
+
- lib/clifton_lib/xml/xml_attribute.rb
|
55
|
+
- lib/clifton_lib/xml/xml_declaration_node.rb
|
56
|
+
- lib/clifton_lib/xml/xml_document.rb
|
57
|
+
- lib/clifton_lib/xml/xml_element.rb
|
58
|
+
- lib/clifton_lib/xml/xml_node.rb
|
59
|
+
- lib/clifton_lib/xml/xml_text_writer.rb
|
60
|
+
- test/xml_document_tests.rb
|
61
|
+
homepage: https://github.com/cliftonm/clifton_lib
|
62
|
+
licenses:
|
63
|
+
- MIT
|
64
|
+
post_install_message:
|
65
|
+
rdoc_options: []
|
66
|
+
require_paths:
|
67
|
+
- lib
|
68
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
69
|
+
none: false
|
70
|
+
requirements:
|
71
|
+
- - ! '>='
|
72
|
+
- !ruby/object:Gem::Version
|
73
|
+
version: '0'
|
74
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
75
|
+
none: false
|
76
|
+
requirements:
|
77
|
+
- - ! '>='
|
78
|
+
- !ruby/object:Gem::Version
|
79
|
+
version: '0'
|
80
|
+
requirements: []
|
81
|
+
rubyforge_project:
|
82
|
+
rubygems_version: 1.8.16
|
83
|
+
signing_key:
|
84
|
+
specification_version: 3
|
85
|
+
summary: Collection of useful helper classes.
|
86
|
+
test_files:
|
87
|
+
- test/xml_document_tests.rb
|