XmlEasy 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/History.txt ADDED
@@ -0,0 +1,5 @@
1
+ == 1.0.0 / 2007-12-08
2
+
3
+ * 1 major enhancement
4
+ * Birthday!
5
+
data/Manifest.txt ADDED
@@ -0,0 +1,8 @@
1
+ History.txt
2
+ Manifest.txt
3
+ README.txt
4
+ Rakefile
5
+ bin/xml_easy
6
+ lib/xml_easy.rb
7
+ test/test_xml_easy.rb
8
+ test/test.xml
data/README.txt ADDED
@@ -0,0 +1,51 @@
1
+ XmlEasy
2
+ by ANDO Yasushi
3
+ andyjpn@gmail.com
4
+
5
+ == DESCRIPTION:
6
+
7
+ ruby-easy offers you a way to handle xml quite easily.
8
+
9
+ == FEATURES/PROBLEMS:
10
+
11
+ * handle xml
12
+
13
+ == SYNOPSIS:
14
+
15
+ xml_easy = XmlEasy::Document.new 'text.html'
16
+
17
+ # return a link target for the 3rd item in sidebar
18
+ xml_easy.html.body.div{|e| e[:class] == 'sidebar'}.li[3].a[:href]
19
+
20
+ == REQUIREMENTS:
21
+
22
+ * cosmetics
23
+
24
+ == INSTALL:
25
+
26
+ * sudo gem install xml-easy
27
+
28
+ == LICENSE:
29
+
30
+ (The MIT License)
31
+
32
+ Copyright (c) 2007 FIX
33
+
34
+ Permission is hereby granted, free of charge, to any person obtaining
35
+ a copy of this software and associated documentation files (the
36
+ 'Software'), to deal in the Software without restriction, including
37
+ without limitation the rights to use, copy, modify, merge, publish,
38
+ distribute, sublicense, and/or sell copies of the Software, and to
39
+ permit persons to whom the Software is furnished to do so, subject to
40
+ the following conditions:
41
+
42
+ The above copyright notice and this permission notice shall be
43
+ included in all copies or substantial portions of the Software.
44
+
45
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
46
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
47
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
48
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
49
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
50
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
51
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/Rakefile ADDED
@@ -0,0 +1,18 @@
1
+ # -*- ruby -*-
2
+
3
+ require 'rubygems'
4
+ require 'hoe'
5
+ require './lib/xml_easy.rb'
6
+
7
+ #Hoe.new('XmlEasy', XmlEasy::VERSION) do |p|
8
+ Hoe.new('XmlEasy', XmlEasy::VERSION) do |p|
9
+ p.rubyforge_name = 'xml_easy'
10
+ p.author = 'ANDO Yasushi'
11
+ p.email = 'andyjpn@gmail.com'
12
+ p.summary = 'handle xml easily'
13
+ p.description = p.paragraphs_of('README.txt', 2..5).join("\n\n")
14
+ p.url = p.paragraphs_of('README.txt', 0).first.split(/\n/)[1..-1]
15
+ p.changes = p.paragraphs_of('History.txt', 0..1).join("\n\n")
16
+ end
17
+
18
+ # vim: syntax=Ruby
data/bin/xml_easy ADDED
File without changes
data/lib/xml_easy.rb ADDED
@@ -0,0 +1,246 @@
1
+ require 'stringio'
2
+ require 'rexml/document'
3
+ require 'rexml/parsers/streamparser'
4
+ require 'rexml/parsers/baseparser'
5
+ require 'rexml/streamlistener'
6
+
7
+ class Array
8
+ def method_missing(name, *args, &block)
9
+ if all? {|e| nil? or e.class == XmlEasy::Element}
10
+ elms = map{|e| e.send(name, *args, &block) rescue nil}.flatten.compact
11
+ unless block.nil?
12
+ elms = elms.select &block
13
+ end
14
+ elms
15
+ else
16
+ raise NoMethodError.new(name)
17
+ end
18
+ end
19
+ end
20
+
21
+ class HashWithIndifferentAccess < Hash
22
+ def get_with_indifferent_access(key)
23
+ self[key.to_s] || self[key.to_sym]
24
+ end
25
+ alias get_with_indifferent_access []
26
+
27
+ def set_with_indifferent_access(key, val)
28
+ self[key.to_s] = val
29
+ end
30
+ alias set_with_indifferent_access []=
31
+ end
32
+
33
+ class XmlEasy
34
+ VERSION = '0.0.1'
35
+
36
+ class EasyListener
37
+ include REXML::StreamListener
38
+ def initialize(doc)
39
+ @doc = doc
40
+ @current = doc.root
41
+ end
42
+
43
+ def attlistdecl(elm_name, attrs, content); end
44
+ def cdata(content); end
45
+ def comment(content); end
46
+ def elementdecl(content); end
47
+ def entity(content); end
48
+ def instruction(name, inst); end
49
+ def notationdecl(content); end
50
+
51
+ def xmldecl(version, encoding, standalone)
52
+ @doc.xml_dec = "<?xml#{
53
+ version ? " version='#{version}'" : ''
54
+ }#{
55
+ encoding ? " encoding='#{encoding}'" : ''
56
+ }#{
57
+ standalone ? " standalone='#{standalone}'" : ''
58
+ }?>"
59
+ end
60
+
61
+ def doctype(name, pub_sys, long_name, uri)
62
+ #TODO: temporary
63
+ @doc.doc_type = "<!DOCTYPE window [<!ENTITY nl '&#38;#10;'>]>"
64
+ end
65
+
66
+ def entitydecl(content)
67
+ end
68
+
69
+ def doctype_end
70
+ end
71
+
72
+ def tag_start(name, attrs)
73
+ element = Element.new name
74
+ attrs.each{|k, v| element[k] = v.gsub('"', '&quot;').inspect}
75
+ @current << element
76
+ @current = element
77
+ end
78
+
79
+ def tag_end(name)
80
+ if @current.name == name.to_sym
81
+ @current = @current.parent
82
+ else
83
+ raise RuntimeError.new("unmatch end-tag: #{name.inspect}")
84
+ end
85
+ end
86
+
87
+ def text(content)
88
+ @current.body = content
89
+ end
90
+ end
91
+
92
+ class Document
93
+ attr_accessor :xml_dec, :doc_type, :root
94
+
95
+ def initialize(filename=nil)
96
+ @root = Element.new
97
+ @filename = filename
98
+ if @filename =~ /^<.*$/
99
+ REXML::Document.parse_stream StringIO.new(filename), EasyListener.new(self)
100
+ else
101
+ REXML::Document.parse_stream File.new(filename), EasyListener.new(self) if @filename
102
+ end
103
+ end
104
+
105
+ def copy
106
+ copied = self.class.new
107
+ copied.xml_dec = @xml_dec
108
+ copied.doc_type = @doc_type
109
+ copied.root = @root.copy
110
+ copied
111
+ end
112
+
113
+ def to_s
114
+ <<-eos
115
+ #{@xml_dec}
116
+ #{@doc_type}
117
+ #{@root.children.first.to_s}
118
+ eos
119
+ end
120
+
121
+ def method_missing(name, *args, &block)
122
+ @root.send name
123
+ end
124
+ end
125
+
126
+ class Element
127
+ attr_accessor :parent, :children, :name, :body, :attributes
128
+
129
+ def initialize(name=nil)
130
+ @parent = nil
131
+ @name = name.to_sym if name
132
+ @body = ''
133
+ @attributes = HashWithIndifferentAccess.new
134
+ @children = []
135
+ end
136
+
137
+ def body=(content)
138
+ if @body =~ /^\s+$/m
139
+ @body = ''
140
+ else
141
+ @body = content
142
+ end
143
+ self
144
+ end
145
+
146
+ def []=(key, val)
147
+ val = $1 if val =~ /^"(.*)"$/ or val =~ /^"(.*)"$/ #TODO
148
+ @attributes[key.to_s] = val
149
+ self
150
+ end
151
+
152
+ def [](key)
153
+ @attributes[key.to_s]
154
+ end
155
+
156
+ def <<(element, option=nil)
157
+ case option
158
+ when NilClass
159
+ @children << element
160
+ when Hash
161
+ if option[:after]
162
+ @children.insert @children.index(option[:after]) + 1, element
163
+ elsif option[:before]
164
+ @children.insert @children.index(option[:before]), element
165
+ end
166
+ when String, Symbol
167
+ case option.to_sym
168
+ when :top
169
+ @children.unshift element
170
+ when :bottom
171
+ @children << element
172
+ else
173
+ raise ArgumentError.new('invalid argument')
174
+ end
175
+ else
176
+ raise ArgumentError.new('invalid argument')
177
+ end
178
+ element.parent = self
179
+ end
180
+
181
+ def prune_children(num)
182
+ @children = @children[0...num]
183
+ end
184
+
185
+ def remove
186
+ @parent.children.delete self
187
+ end
188
+
189
+ def each(&block)
190
+ @children.each &block
191
+ end
192
+
193
+ def each_attribute(&block)
194
+ @attributes.each &block
195
+ end
196
+
197
+ def to_s(indent=0)
198
+ "#{"\t" * indent}<#{@name}" +
199
+ unless @attributes.empty?
200
+ "\n#{@attributes.to_a.map{|k, v| "#{"\t" * (indent + 1)} #{k}=#{v.inspect}"}.join("\n")}"
201
+ else
202
+ ''
203
+ end +
204
+ if @children.empty? and @body.empty?
205
+ " />\n"
206
+ elsif !@body.empty? and @children.empty?
207
+ ">#{@body}\n#{"\t" * indent}</#{@name}>\n"
208
+ else
209
+ ">\n#{@children.map{|c| c.to_s(indent + 1)}.join}#{"\t" * indent}</#{@name}>\n"
210
+ end
211
+ end
212
+
213
+ def copy
214
+ copied = self.class.new @name
215
+ copied.body = @body
216
+ copied.attributes = HashWithIndifferentAccess[@attributes]
217
+ @children.each do |c|
218
+ copied << c
219
+ end
220
+ copied
221
+ end
222
+
223
+ def method_missing(name, *args, &block)
224
+ if name == :each_with_index
225
+ [self].each_with_index &block
226
+ return
227
+ end
228
+ children = @children.select {|c| c.name == name.to_sym}
229
+ if children.empty?
230
+ name = name.to_s.sub(/^(.*)_$/, '\1').to_sym
231
+ children = @children.select {|c| c.name == name.to_sym}
232
+ end
233
+ unless block.nil?
234
+ children = children.select &block
235
+ end
236
+ if children.empty?
237
+ #puts "<#{name}> does not exist in <#{@name}>."
238
+ raise NameError.new(name)
239
+ elsif children.size == 1
240
+ children.first
241
+ else
242
+ children
243
+ end
244
+ end
245
+ end
246
+ end
data/test/test.xml ADDED
@@ -0,0 +1,5 @@
1
+ <?xml version="1.0"?>
2
+ <root>
3
+ <child1></child1>
4
+ <child2 attr1="val1"></child2>
5
+ </root>
@@ -0,0 +1,122 @@
1
+ require 'test/unit'
2
+ require 'lib/xml_easy'
3
+
4
+ class XmlEasyTest < Test::Unit::TestCase
5
+ TEST_XML = "#{File.dirname(__FILE__)}/test.xml"
6
+ def setup
7
+ @xml = XmlEasy::Document.new TEST_XML
8
+ end
9
+
10
+ def test_new_doc_with_string
11
+ xml = XmlEasy::Document.new <<-target
12
+ <?xml version="1.0"?>
13
+ <root attr="new with string">
14
+ <child1></child1>
15
+ <child2 attr1="val1"></child2>
16
+ </root>
17
+ target
18
+
19
+ assert_element <<-expected, xml
20
+ <?xml version='1.0'?>
21
+
22
+ <root
23
+ attr="new with string">
24
+ <child1 />
25
+ <child2
26
+ attr1="val1" />
27
+ </root>
28
+ expected
29
+ end
30
+
31
+ def test_access_to_child
32
+ assert_equal "<child1 />\n", @xml.root_.child1.to_s
33
+ end
34
+
35
+ def test_insert_after
36
+ c1 = @xml.root_.child1
37
+ c2 = @xml.root_.child2
38
+
39
+ c21 = c2.copy
40
+ c21[:attr1] = 'val11'
41
+ c1.parent.<< c21, :after => c2
42
+ assert_element <<-expected, @xml
43
+ <?xml version='1.0'?>
44
+
45
+ <root>
46
+ <child1 />
47
+ <child2
48
+ attr1="val1" />
49
+ <child2
50
+ attr1="val11" />
51
+ </root>
52
+ expected
53
+ end
54
+
55
+ def test_insert_before
56
+ c1 = @xml.root_.child1
57
+ c2 = @xml.root_.child2
58
+
59
+ c22 = c2.copy
60
+ c22[:attr1] = 'val12'
61
+ c1.parent.<< c22, :before => c2
62
+ assert_element <<-expected, @xml
63
+ <?xml version='1.0'?>
64
+
65
+ <root>
66
+ <child1 />
67
+ <child2
68
+ attr1="val12" />
69
+ <child2
70
+ attr1="val1" />
71
+ </root>
72
+ expected
73
+ end
74
+
75
+ def test_insert_top
76
+ c1 = @xml.root_.child1
77
+ c2 = @xml.root_.child2
78
+
79
+ c23 = c2.copy
80
+ c23[:attr1] = 'val13'
81
+ c1.parent.<< c23, :top
82
+ assert_element <<-expected, @xml
83
+ <?xml version='1.0'?>
84
+
85
+ <root>
86
+ <child2
87
+ attr1="val13" />
88
+ <child1 />
89
+ <child2
90
+ attr1="val1" />
91
+ </root>
92
+ expected
93
+ end
94
+
95
+ def test_insert_bottom
96
+ c1 = @xml.root_.child1
97
+ c2 = @xml.root_.child2
98
+
99
+ c24 = c2.copy
100
+ c24[:attr1] = 'val14'
101
+ c1.parent.<< c24, :bottom
102
+ assert_element <<-expected, @xml
103
+ <?xml version='1.0'?>
104
+
105
+ <root>
106
+ <child1 />
107
+ <child2
108
+ attr1="val1" />
109
+ <child2
110
+ attr1="val14" />
111
+ </root>
112
+ expected
113
+ end
114
+
115
+ protected
116
+
117
+ def assert_element(expected, element)
118
+ assert_equal expected.strip, element.to_s.strip.gsub("\t", ' ')
119
+ end
120
+ end
121
+
122
+
metadata ADDED
@@ -0,0 +1,64 @@
1
+ --- !ruby/object:Gem::Specification
2
+ rubygems_version: 0.9.4
3
+ specification_version: 1
4
+ name: XmlEasy
5
+ version: !ruby/object:Gem::Version
6
+ version: 0.0.1
7
+ date: 2007-12-08 00:00:00 +09:00
8
+ summary: handle xml easily
9
+ require_paths:
10
+ - lib
11
+ email: andyjpn@gmail.com
12
+ homepage: " by ANDO Yasushi"
13
+ rubyforge_project: xml_easy
14
+ description: "ruby-easy offers you a way to handle xml quite easily. == FEATURES/PROBLEMS: * handle xml == SYNOPSIS: xml_easy = XmlEasy::Document.new 'text.html'"
15
+ autorequire:
16
+ default_executable:
17
+ bindir: bin
18
+ has_rdoc: true
19
+ required_ruby_version: !ruby/object:Gem::Version::Requirement
20
+ requirements:
21
+ - - ">"
22
+ - !ruby/object:Gem::Version
23
+ version: 0.0.0
24
+ version:
25
+ platform: ruby
26
+ signing_key:
27
+ cert_chain:
28
+ post_install_message:
29
+ authors:
30
+ - ANDO Yasushi
31
+ files:
32
+ - History.txt
33
+ - Manifest.txt
34
+ - README.txt
35
+ - Rakefile
36
+ - bin/xml_easy
37
+ - lib/xml_easy.rb
38
+ - test/test_xml_easy.rb
39
+ - test/test.xml
40
+ test_files:
41
+ - test/test_xml_easy.rb
42
+ rdoc_options:
43
+ - --main
44
+ - README.txt
45
+ extra_rdoc_files:
46
+ - History.txt
47
+ - Manifest.txt
48
+ - README.txt
49
+ executables:
50
+ - xml_easy
51
+ extensions: []
52
+
53
+ requirements: []
54
+
55
+ dependencies:
56
+ - !ruby/object:Gem::Dependency
57
+ name: hoe
58
+ version_requirement:
59
+ version_requirements: !ruby/object:Gem::Version::Requirement
60
+ requirements:
61
+ - - ">="
62
+ - !ruby/object:Gem::Version
63
+ version: 1.3.0
64
+ version: