xmlcodec 0.0.3 → 0.0.4
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/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:
|