xmlcodec 0.0.3 → 0.0.4
Sign up to get free protection for your applications and to get access to all the features.
- data/Rakefile +1 -1
- data/lib/XMLElement.rb +5 -0
- data/lib/XMLStreamObjectParser.rb +6 -4
- data/lib/XMLStreamParser.rb +3 -7
- data/lib/XMLUtils.rb +50 -2
- data/test/TestPartialExport.rb +27 -0
- data/test/TestXMLStreamObjectParser.rb +27 -17
- data/test/TestXMLStreamParser.rb +36 -36
- data/test/TestXMLUtils.rb +43 -10
- data/test/simple_objects.rb +6 -0
- metadata +4 -3
data/Rakefile
CHANGED
data/lib/XMLElement.rb
CHANGED
@@ -491,6 +491,11 @@ module XMLCodec
|
|
491
491
|
if not already_partial_export_ended?
|
492
492
|
@already_partial_export_ended = true
|
493
493
|
|
494
|
+
if not already_partial_exported?
|
495
|
+
raise "<#{self} Trying to end the export of an element that hasn't"+
|
496
|
+
" been started yet"
|
497
|
+
end
|
498
|
+
|
494
499
|
each_subelement do |e|
|
495
500
|
e.end_partial_export(file)
|
496
501
|
end
|
@@ -5,13 +5,13 @@ module XMLCodec
|
|
5
5
|
# This class is used internally by the parser to store the information about
|
6
6
|
# each of the elements that gets created.
|
7
7
|
class XMLSOParserElement
|
8
|
-
attr_reader :elclass, :consumed, :id
|
8
|
+
attr_reader :elclass, :consumed, :id, :depth
|
9
9
|
|
10
10
|
# Create a new instance with the element name, a hash of atributes, it's
|
11
11
|
# import/export class, the parent element and it's id
|
12
12
|
# The id is used to fill in element_id and parent_id in XMLElement so that
|
13
13
|
# the parser's user can know what is the tree structure between objects.
|
14
|
-
def initialize(name, attrs, elclass, parent, id)
|
14
|
+
def initialize(name, attrs, elclass, parent, id, depth)
|
15
15
|
@attrs = attrs
|
16
16
|
@elclass = elclass
|
17
17
|
@children = Hash.new([])
|
@@ -21,6 +21,7 @@ module XMLCodec
|
|
21
21
|
@parent = parent
|
22
22
|
@id = id
|
23
23
|
@name = name
|
24
|
+
@depth = depth
|
24
25
|
end
|
25
26
|
|
26
27
|
# Add a child element to the object
|
@@ -65,7 +66,7 @@ module XMLCodec
|
|
65
66
|
@listener = listener
|
66
67
|
@children = Hash.new([])
|
67
68
|
@currel = 0
|
68
|
-
@elements = [XMLSOParserElement.new(nil, nil, nil, nil, nil)]
|
69
|
+
@elements = [XMLSOParserElement.new(nil, nil, nil, nil, nil, 0)]
|
69
70
|
@id = 0
|
70
71
|
@top_element = nil
|
71
72
|
end
|
@@ -102,7 +103,8 @@ module XMLCodec
|
|
102
103
|
|
103
104
|
def tag_start(name, attrs) #:nodoc:
|
104
105
|
@elements << XMLSOParserElement.new(name, attrs, get_elclass(name),
|
105
|
-
curr_element, next_id
|
106
|
+
curr_element, next_id,
|
107
|
+
curr_element.depth+1)
|
106
108
|
@currel += 1
|
107
109
|
end
|
108
110
|
|
data/lib/XMLStreamParser.rb
CHANGED
@@ -91,7 +91,9 @@ module XMLUtils
|
|
91
91
|
|
92
92
|
def tag_end(name)
|
93
93
|
@contents << "</"+name+">"
|
94
|
-
|
94
|
+
if @listener.respond_to? 'el_'+name
|
95
|
+
@listener.send('el_'+name, @elements[-1])
|
96
|
+
end
|
95
97
|
@elements.pop()
|
96
98
|
end
|
97
99
|
|
@@ -99,12 +101,6 @@ module XMLUtils
|
|
99
101
|
@contents.text_from(@elements[-1].elstart)
|
100
102
|
end
|
101
103
|
|
102
|
-
def element(name)
|
103
|
-
if @listener
|
104
|
-
@listener.element(@elements[-1])
|
105
|
-
end
|
106
|
-
end
|
107
|
-
|
108
104
|
def consume
|
109
105
|
@contents.erase_from(@elements[-1].elstart)
|
110
106
|
end
|
data/lib/XMLUtils.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
|
-
require
|
1
|
+
require 'rexml/document'
|
2
|
+
require 'stringio'
|
2
3
|
|
3
4
|
# This module holds generic XML utilities. The module's methods are simple
|
4
5
|
# XML utilities. The module also contains XMLStreamParser, a Generic XML Stream
|
@@ -16,7 +17,7 @@ module XMLUtils
|
|
16
17
|
def self.count_elements(path, filename)
|
17
18
|
doc = getdoc(filename)
|
18
19
|
i = 0
|
19
|
-
XPath.each(doc, path) {|element| i+=1}
|
20
|
+
REXML::XPath.each(doc, path) {|element| i+=1}
|
20
21
|
return i
|
21
22
|
end
|
22
23
|
|
@@ -55,4 +56,51 @@ module XMLUtils
|
|
55
56
|
t.write_with_substitution(str, string)
|
56
57
|
str
|
57
58
|
end
|
59
|
+
|
60
|
+
# Gets the xpath inside a given document that can either be a string or a
|
61
|
+
# REXML::Document
|
62
|
+
#
|
63
|
+
# opts can have:
|
64
|
+
# :multiple: fetch all the occurences of the xpath
|
65
|
+
# :with_attrs: include the attribute contents in the result
|
66
|
+
# :recursive: recursively include all the subelements of the matches
|
67
|
+
def self.get_xpath(path, doc, opts={})
|
68
|
+
if doc.is_a? REXML::Document
|
69
|
+
doc = doc
|
70
|
+
else
|
71
|
+
doc = REXML::Document.new(doc)
|
72
|
+
end
|
73
|
+
|
74
|
+
if opts[:multiple]
|
75
|
+
strs = []
|
76
|
+
REXML::XPath.each(doc.root, path) do |e|
|
77
|
+
t = get_rexml_content(e, opts)
|
78
|
+
strs << t if t != ''
|
79
|
+
end
|
80
|
+
return strs.join(' ')
|
81
|
+
else
|
82
|
+
return get_rexml_content(REXML::XPath.first(doc, path), opts)
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
def self.get_rexml_content(element, opts={})
|
87
|
+
return '' if not element
|
88
|
+
strs = []
|
89
|
+
if element.respond_to?('value')
|
90
|
+
return element.value || ''
|
91
|
+
else
|
92
|
+
if opts[:with_attrs]
|
93
|
+
element.attributes.each {|name, value| strs << value if value != ''}
|
94
|
+
end
|
95
|
+
if not opts[:recursive]
|
96
|
+
element.texts.each {|t| strs << t if t != ''}
|
97
|
+
else
|
98
|
+
element.to_a.each do |e|
|
99
|
+
t = get_rexml_content(e, opts)
|
100
|
+
strs << t if t != ''
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
104
|
+
strs.join(' ')
|
105
|
+
end
|
58
106
|
end
|
data/test/TestPartialExport.rb
CHANGED
@@ -142,4 +142,31 @@ class TestPartialExport < Test::Unit::TestCase
|
|
142
142
|
compare_xpath(value1, filename, "/subels/abc[1]")
|
143
143
|
compare_xpath(value2, filename, "/subels/abc[2]")
|
144
144
|
end
|
145
|
+
|
146
|
+
def test_recursive
|
147
|
+
filename = 'test_partial_export_recursive.xml'
|
148
|
+
file = File.open(filename, "w")
|
149
|
+
|
150
|
+
value = 'somevalue'
|
151
|
+
|
152
|
+
rec1 = Recursive.new
|
153
|
+
rec1.start_partial_export(file)
|
154
|
+
|
155
|
+
rec2 = Recursive.new
|
156
|
+
rec1.recursive << rec2
|
157
|
+
rec2.start_partial_export(file)
|
158
|
+
|
159
|
+
rec3 = Recursive.new
|
160
|
+
rec2.recursive << rec3
|
161
|
+
rec3.start_partial_export(file)
|
162
|
+
|
163
|
+
sel = SimpleElement.new(value)
|
164
|
+
sel.start_partial_export(file)
|
165
|
+
rec3.abc = sel
|
166
|
+
|
167
|
+
rec1.end_partial_export(file)
|
168
|
+
|
169
|
+
file.close
|
170
|
+
validate_well_formed(filename)
|
171
|
+
end
|
145
172
|
end
|
@@ -7,19 +7,19 @@ include XMLCodec
|
|
7
7
|
class MyStreamListener
|
8
8
|
attr_reader :abc, :subels, :mult, :subel
|
9
9
|
def el_abc(el)
|
10
|
-
@abc = el
|
10
|
+
@abc = el
|
11
11
|
end
|
12
12
|
|
13
13
|
def el_subels(el)
|
14
|
-
@subels = el
|
14
|
+
@subels = el
|
15
15
|
end
|
16
16
|
|
17
17
|
def el_mult(el)
|
18
|
-
@mult = el
|
18
|
+
@mult = el
|
19
19
|
end
|
20
20
|
|
21
21
|
def el_subel(el)
|
22
|
-
@subel = el
|
22
|
+
@subel = el
|
23
23
|
end
|
24
24
|
end
|
25
25
|
|
@@ -28,7 +28,7 @@ class MyConsumingStreamListener
|
|
28
28
|
|
29
29
|
def el_abc(el)
|
30
30
|
el.consume
|
31
|
-
@abc = el
|
31
|
+
@abc = el
|
32
32
|
end
|
33
33
|
end
|
34
34
|
|
@@ -46,7 +46,7 @@ class TestXMLStreamObjectParser < Test::Unit::TestCase
|
|
46
46
|
listener = MyStreamListener.new
|
47
47
|
parser = XMLStreamObjectParser.new(listener)
|
48
48
|
parser.parse(file)
|
49
|
-
el = listener.abc
|
49
|
+
el = listener.abc.get_object
|
50
50
|
assert_equal el.value, value
|
51
51
|
end
|
52
52
|
|
@@ -59,7 +59,7 @@ class TestXMLStreamObjectParser < Test::Unit::TestCase
|
|
59
59
|
parser = XMLStreamObjectParser.new(listener)
|
60
60
|
parser.parse(file)
|
61
61
|
|
62
|
-
el = listener.abc
|
62
|
+
el = listener.abc.get_object
|
63
63
|
assert_equal el.value, value
|
64
64
|
|
65
65
|
subel = parser.top_element
|
@@ -67,10 +67,6 @@ class TestXMLStreamObjectParser < Test::Unit::TestCase
|
|
67
67
|
assert_equal attrvalue, subel.someattr
|
68
68
|
end
|
69
69
|
|
70
|
-
def test_multiple_names
|
71
|
-
|
72
|
-
end
|
73
|
-
|
74
70
|
def test_mult
|
75
71
|
value = 'somevalue'
|
76
72
|
file = '<mult><abc>'+value+'</abc></mult>'
|
@@ -79,7 +75,7 @@ class TestXMLStreamObjectParser < Test::Unit::TestCase
|
|
79
75
|
parser = XMLStreamObjectParser.new(listener)
|
80
76
|
parser.parse(file)
|
81
77
|
|
82
|
-
el = listener.abc
|
78
|
+
el = listener.abc.get_object
|
83
79
|
assert_equal el.value, value
|
84
80
|
assert_equal el, parser.top_element.abc[0]
|
85
81
|
end
|
@@ -92,7 +88,7 @@ class TestXMLStreamObjectParser < Test::Unit::TestCase
|
|
92
88
|
parser = XMLStreamObjectParser.new(listener)
|
93
89
|
parser.parse(file)
|
94
90
|
|
95
|
-
el = listener.abc
|
91
|
+
el = listener.abc.get_object
|
96
92
|
assert_equal el.value, value
|
97
93
|
assert_equal el, parser.top_element.subelements[0]
|
98
94
|
end
|
@@ -105,7 +101,7 @@ class TestXMLStreamObjectParser < Test::Unit::TestCase
|
|
105
101
|
parser = XMLStreamObjectParser.new(listener)
|
106
102
|
parser.parse(file)
|
107
103
|
|
108
|
-
el = listener.abc
|
104
|
+
el = listener.abc.get_object
|
109
105
|
assert_equal el.value, value
|
110
106
|
assert_nil parser.top_element.abc
|
111
107
|
end
|
@@ -119,7 +115,7 @@ class TestXMLStreamObjectParser < Test::Unit::TestCase
|
|
119
115
|
parser = XMLStreamObjectParser.new(listener)
|
120
116
|
parser.parse(file)
|
121
117
|
|
122
|
-
el = listener.subels
|
118
|
+
el = listener.subels.get_object
|
123
119
|
assert_equal 2, el.subelements.size
|
124
120
|
[value1, value2].each_with_index do |value, index|
|
125
121
|
assert_kind_of SimpleElementMultName, el.subelements[index]
|
@@ -136,7 +132,7 @@ class TestXMLStreamObjectParser < Test::Unit::TestCase
|
|
136
132
|
parser = XMLStreamObjectParser.new(listener)
|
137
133
|
parser.parse(file)
|
138
134
|
|
139
|
-
el = listener.mult
|
135
|
+
el = listener.mult.get_object
|
140
136
|
assert_equal 2, el.abc2.size
|
141
137
|
[value1, value2].each_with_index do |value, index|
|
142
138
|
assert_kind_of SimpleElementMultName, el.abc2[index]
|
@@ -152,9 +148,23 @@ class TestXMLStreamObjectParser < Test::Unit::TestCase
|
|
152
148
|
parser = XMLStreamObjectParser.new(listener)
|
153
149
|
parser.parse(file)
|
154
150
|
|
155
|
-
el = listener.subel
|
151
|
+
el = listener.subel.get_object
|
156
152
|
assert_not_nil el.abc2
|
157
153
|
assert_kind_of SimpleElementMultName, el.abc2
|
158
154
|
assert_equal value, el.abc2.value
|
159
155
|
end
|
156
|
+
|
157
|
+
def test_depth
|
158
|
+
value = 'somevalue'
|
159
|
+
file = '<subel><abc>'+value+'</abc></subel>'
|
160
|
+
|
161
|
+
listener = MyStreamListener.new
|
162
|
+
parser = XMLStreamObjectParser.new(listener)
|
163
|
+
parser.parse(file)
|
164
|
+
|
165
|
+
el1 = listener.subel
|
166
|
+
el2 = listener.abc
|
167
|
+
|
168
|
+
assert el1.depth < el2.depth
|
169
|
+
end
|
160
170
|
end
|
data/test/TestXMLStreamParser.rb
CHANGED
@@ -4,44 +4,44 @@ $-w = true
|
|
4
4
|
require 'test/unit'
|
5
5
|
require 'XMLStreamParser'
|
6
6
|
|
7
|
-
class
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
7
|
+
class MyXMLStreamListener
|
8
|
+
attr_reader :def_id, :def_parent_id
|
9
|
+
attr_reader :abc_id, :abc_parent_id
|
10
|
+
|
11
|
+
def el_def(el)
|
12
|
+
@def_id, = el.element_id
|
13
|
+
@def_parent_id = el.parent_id
|
14
|
+
el.consume
|
15
|
+
end
|
16
|
+
|
17
|
+
def el_abc(el)
|
18
|
+
@abc_id, = el.element_id
|
19
|
+
@abc_parent_id = el.parent_id
|
20
|
+
el.consume
|
21
|
+
end
|
22
22
|
end
|
23
23
|
|
24
24
|
class TestXMLStreamParser < Test::Unit::TestCase
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
25
|
+
def initialize(*args)
|
26
|
+
super(*args)
|
27
|
+
@doc = "<abc attr1='1' attr2='2'>abc<xpto attr1='a'></xpto><def><x></x></def></abc>"
|
28
|
+
@doc_no_def = "<abc attr1='1' attr2='2'>abc<xpto attr1='a'></xpto></abc>"
|
29
|
+
end
|
30
30
|
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
31
|
+
def test_total_parse
|
32
|
+
parser = XMLUtils::XMLStreamParser.new
|
33
|
+
parser.parse(@doc)
|
34
|
+
assert_equal(@doc, parser.content)
|
35
|
+
end
|
36
|
+
|
37
|
+
def test_consumed_parse
|
38
|
+
listener = MyXMLStreamListener.new
|
39
|
+
parser = XMLUtils::XMLStreamParser.new(listener)
|
40
|
+
parser.parse(@doc)
|
41
|
+
assert_equal(@doc_no_def, parser.content)
|
42
|
+
assert_equal(listener.abc_id, listener.def_parent_id)
|
43
|
+
assert_equal(0, listener.abc_parent_id)
|
44
|
+
assert_equal(1, listener.abc_id)
|
45
|
+
assert(listener.def_id > listener.def_parent_id)
|
46
|
+
end
|
47
47
|
end
|
data/test/TestXMLUtils.rb
CHANGED
@@ -4,14 +4,47 @@ require 'test/unit'
|
|
4
4
|
require 'XMLUtils'
|
5
5
|
|
6
6
|
class TestXMLUtils < Test::Unit::TestCase
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
7
|
+
def test_create_open_tag
|
8
|
+
tag = XMLUtils::create_open_tag("name", {"arg1" => "val1", "arg2" => "val2"})
|
9
|
+
assert_equal("<name arg1='val1' arg2='val2'>", tag)
|
10
|
+
end
|
11
|
+
|
12
|
+
def test_escape_xml
|
13
|
+
assert_equal '< abc', XMLUtils::escape_xml('< abc')
|
14
|
+
assert_equal '> abc', XMLUtils::escape_xml('> abc')
|
15
|
+
assert_equal '& abc', XMLUtils::escape_xml('& abc')
|
16
|
+
end
|
17
|
+
|
18
|
+
def test_get_xpath
|
19
|
+
opts = {}
|
20
|
+
assert_xpath_equal('abc', '//xpto', '<xpto>abc<xpto>')
|
21
|
+
|
22
|
+
assert_xpath_equal('abc', '//xpto', '<xpto>abc<xpto2>foo</xpto2><xpto>')
|
23
|
+
|
24
|
+
opts[:with_attrs] = true
|
25
|
+
opts[:recursive] = false
|
26
|
+
opts[:multiple] = false
|
27
|
+
assert_xpath_equal('attr1 abc', '//xpto', '<xpto attr1="attr1">abc<xpto2>foo</xpto2><xpto>', opts)
|
28
|
+
|
29
|
+
opts[:with_attrs] = false
|
30
|
+
opts[:recursive] = true
|
31
|
+
opts[:multiple] = false
|
32
|
+
assert_xpath_equal('abc foo', '//xpto', '<xpto>abc<xpto2 attr1="attr1">foo</xpto2><xpto>', opts)
|
33
|
+
|
34
|
+
opts[:with_attrs] = true
|
35
|
+
opts[:recursive] = true
|
36
|
+
opts[:multiple] = false
|
37
|
+
assert_xpath_equal('abc attr1 foo', '//xpto', '<xpto>abc<xpto2 attr1="attr1">foo</xpto2><xpto>', opts)
|
38
|
+
|
39
|
+
opts[:with_attrs] = false
|
40
|
+
opts[:recursive] = false
|
41
|
+
opts[:multiple] = true
|
42
|
+
assert_xpath_equal('abc foo', '//xpto', '<xpto>abc<xpto attr1="attr1">foo</xpto><xpto>', opts)
|
43
|
+
end
|
44
|
+
|
45
|
+
def assert_xpath_equal(result, path, xml, opts={})
|
46
|
+
assert_equal result, XMLUtils::get_xpath(path, xml, opts)
|
47
|
+
assert_equal result, XMLUtils::get_xpath(path, StringIO.new(xml), opts)
|
48
|
+
assert_equal result, XMLUtils::get_xpath(path, REXML::Document.new(xml), opts)
|
49
|
+
end
|
17
50
|
end
|
data/test/simple_objects.rb
CHANGED
metadata
CHANGED
@@ -1,10 +1,10 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
|
-
rubygems_version: 0.
|
2
|
+
rubygems_version: 0.9.0
|
3
3
|
specification_version: 1
|
4
4
|
name: xmlcodec
|
5
5
|
version: !ruby/object:Gem::Version
|
6
|
-
version: 0.0.
|
7
|
-
date: 2006-
|
6
|
+
version: 0.0.4
|
7
|
+
date: 2006-07-06 00:00:00 +01:00
|
8
8
|
summary: Generic Importer/Exporter of XML formats
|
9
9
|
require_paths:
|
10
10
|
- lib
|
@@ -25,6 +25,7 @@ required_ruby_version: !ruby/object:Gem::Version::Requirement
|
|
25
25
|
platform: ruby
|
26
26
|
signing_key:
|
27
27
|
cert_chain:
|
28
|
+
post_install_message:
|
28
29
|
authors:
|
29
30
|
- "Pedro C\xC3\xB4rte-Real"
|
30
31
|
files:
|