tilia-xml 1.2.0.2 → 1.3.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/.simplecov +1 -2
- data/CHANGELOG.sabre.md +21 -0
- data/Gemfile +2 -7
- data/Gemfile.lock +22 -17
- data/LICENSE +1 -1
- data/LICENSE.sabre +1 -1
- data/lib/tilia/xml.rb +3 -0
- data/lib/tilia/xml/context_stack_trait.rb +27 -23
- data/lib/tilia/xml/deserializer.rb +241 -0
- data/lib/tilia/xml/element/base.rb +2 -43
- data/lib/tilia/xml/element/cdata.rb +1 -26
- data/lib/tilia/xml/element/elements.rb +4 -66
- data/lib/tilia/xml/element/key_value.rb +3 -65
- data/lib/tilia/xml/element/uri.rb +2 -45
- data/lib/tilia/xml/element/xml_fragment.rb +2 -42
- data/lib/tilia/xml/reader.rb +33 -28
- data/lib/tilia/xml/serializer.rb +194 -0
- data/lib/tilia/xml/service.rb +98 -14
- data/lib/tilia/xml/version.rb +1 -1
- data/lib/tilia/xml/writer.rb +42 -88
- data/lib/tilia/xml/xml_deserializable.rb +4 -4
- data/lib/tilia/xml/xml_serializable.rb +3 -3
- data/test/test_helper.rb +77 -0
- data/test/xml/context_stack_test.rb +0 -3
- data/test/xml/deserializer/enum_test.rb +55 -0
- data/test/xml/deserializer/key_value_test.rb +64 -0
- data/test/xml/deserializer/repeating_elements_test.rb +33 -0
- data/test/xml/deserializer/value_object_test.rb +163 -0
- data/test/xml/reader_test.rb +35 -16
- data/test/xml/serializer/enum_test.rb +36 -0
- data/test/xml/serializer/repeating_elements_test.rb +37 -0
- data/test/xml/service_test.rb +68 -0
- data/test/xml/writer_test.rb +120 -17
- data/tilia-xml.gemspec +4 -4
- metadata +23 -9
@@ -0,0 +1,194 @@
|
|
1
|
+
module Tilia
|
2
|
+
module Xml
|
3
|
+
# This file provides a number of 'serializer' helper functions.
|
4
|
+
#
|
5
|
+
# These helper functions can be used to easily xml-encode common PHP
|
6
|
+
# data structures, or can be placed in the class_map.
|
7
|
+
module Serializer
|
8
|
+
# The 'enum' serializer writes simple list of elements.
|
9
|
+
#
|
10
|
+
# For example, calling:
|
11
|
+
#
|
12
|
+
# enum(writer, [
|
13
|
+
# "{http://sabredav.org/ns}elem1",
|
14
|
+
# "{http://sabredav.org/ns}elem2",
|
15
|
+
# "{http://sabredav.org/ns}elem3",
|
16
|
+
# "{http://sabredav.org/ns}elem4",
|
17
|
+
# "{http://sabredav.org/ns}elem5",
|
18
|
+
# ])
|
19
|
+
#
|
20
|
+
# Will generate something like this (if the correct namespace is declared):
|
21
|
+
#
|
22
|
+
# <s:elem1 />
|
23
|
+
# <s:elem2 />
|
24
|
+
# <s:elem3 />
|
25
|
+
# <s:elem4>content</s:elem4>
|
26
|
+
# <s:elem5 attr="val" />
|
27
|
+
#
|
28
|
+
# @param [Writer] writer
|
29
|
+
# @param [Array<String>] values
|
30
|
+
# @return [void]
|
31
|
+
def self.enum(writer, values)
|
32
|
+
values.each do |value|
|
33
|
+
writer.write_element(value)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
# The valueObject serializer turns a simple PHP object into a classname.
|
38
|
+
#
|
39
|
+
# Every public property will be encoded as an xml element with the same
|
40
|
+
# name, in the XML namespace as specified.
|
41
|
+
#
|
42
|
+
# @param [Writer] writer
|
43
|
+
# @param [Object] value_object
|
44
|
+
# @param [String] namespace
|
45
|
+
def self.value_object(writer, value_object, namespace)
|
46
|
+
value_object.instance_variables.each do |key|
|
47
|
+
value = value_object.instance_variable_get(key)
|
48
|
+
|
49
|
+
# key is a symbol and starts with @
|
50
|
+
key = key.to_s[1..-1]
|
51
|
+
|
52
|
+
writer.write_element("{#{namespace}}#{key}", value)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
# This serializer helps you serialize xml structures that look like
|
57
|
+
# this:
|
58
|
+
#
|
59
|
+
# <collection>
|
60
|
+
# <item>...</item>
|
61
|
+
# <item>...</item>
|
62
|
+
# <item>...</item>
|
63
|
+
# </collection>
|
64
|
+
#
|
65
|
+
# In that previous example, this serializer just serializes the item element,
|
66
|
+
# and this could be called like this:
|
67
|
+
#
|
68
|
+
# repeating_elements(writer, items, '{}item')
|
69
|
+
#
|
70
|
+
# @param [Writer] writer
|
71
|
+
# @param [Array] items A list of items sabre/xml can serialize.
|
72
|
+
# @param [String] child_element_name Element name in clark-notation
|
73
|
+
# @return [void]
|
74
|
+
def self.repeating_elements(writer, items, child_element_name)
|
75
|
+
items.each do |item|
|
76
|
+
writer.write_element(child_element_name, item)
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
# This function is the 'default' serializer that is able to serialize most
|
81
|
+
# things, and delegates to other serializers if needed.
|
82
|
+
#
|
83
|
+
# The standardSerializer supports a wide-array of values.
|
84
|
+
#
|
85
|
+
# value may be a string or integer, it will just write out the string as text.
|
86
|
+
# value may be an instance of XmlSerializable or Element, in which case it
|
87
|
+
# calls it's xml_serialize method.
|
88
|
+
# value may be a PHP callback/function/closure, in case we call the callback
|
89
|
+
# and give it the Writer as an argument.
|
90
|
+
# value may be a an object, and if it's in the classMap we automatically call
|
91
|
+
# the correct serializer for it.
|
92
|
+
# value may be null, in which case we do nothing.
|
93
|
+
#
|
94
|
+
# If value is an array, the array must look like this:
|
95
|
+
#
|
96
|
+
# [
|
97
|
+
# [
|
98
|
+
# 'name' => '{namespaceUri}element-name',
|
99
|
+
# 'value' => '...',
|
100
|
+
# 'attributes' => [ 'attName' => 'attValue' ]
|
101
|
+
# ]
|
102
|
+
# [,
|
103
|
+
# 'name' => '{namespaceUri}element-name2',
|
104
|
+
# 'value' => '...',
|
105
|
+
# ]
|
106
|
+
# ]
|
107
|
+
#
|
108
|
+
# This would result in xml like:
|
109
|
+
#
|
110
|
+
# <element-name xmlns="namespaceUri" attName="attValue">
|
111
|
+
# ...
|
112
|
+
# </element-name>
|
113
|
+
# <element-name2>
|
114
|
+
# ...
|
115
|
+
# </element-name2>
|
116
|
+
#
|
117
|
+
# The value property may be any value standardSerializer supports, so you can
|
118
|
+
# nest data-structures this way. Both value and attributes are optional.
|
119
|
+
#
|
120
|
+
# Alternatively, you can also specify the array using this syntax:
|
121
|
+
#
|
122
|
+
# [
|
123
|
+
# [
|
124
|
+
# '{namespaceUri}element-name' => '...',
|
125
|
+
# '{namespaceUri}element-name2' => '...',
|
126
|
+
# ]
|
127
|
+
# ]
|
128
|
+
#
|
129
|
+
# This is excellent for simple key.value structures, and here you can also
|
130
|
+
# specify anything for the value.
|
131
|
+
#
|
132
|
+
# You can even mix the two array syntaxes.
|
133
|
+
#
|
134
|
+
# @param [Writer] writer
|
135
|
+
# @param value
|
136
|
+
# @return [void]
|
137
|
+
def self.standard_serializer(writer, value)
|
138
|
+
if value.is_a?(Numeric) || value.is_a?(String)
|
139
|
+
writer.write_string(value.to_s)
|
140
|
+
elsif value.is_a?(TrueClass) || value.is_a?(FalseClass)
|
141
|
+
writer.write_string(value.to_s)
|
142
|
+
elsif value.is_a?(XmlSerializable)
|
143
|
+
value.xml_serialize(writer)
|
144
|
+
elsif writer.class_map.key?(value.class)
|
145
|
+
# It's an object which class appears in the classmap.
|
146
|
+
writer.class_map[value.class].call(writer, value)
|
147
|
+
elsif value.respond_to?(:call)
|
148
|
+
# A callback
|
149
|
+
value.call(writer)
|
150
|
+
elsif value.nil?
|
151
|
+
# noop
|
152
|
+
elsif value.is_a?(Hash) || value.is_a?(Array)
|
153
|
+
# Code for ruby implementation
|
154
|
+
if value.is_a?(Array)
|
155
|
+
hash = {}
|
156
|
+
value.each_with_index do |v, i|
|
157
|
+
hash[i] = v
|
158
|
+
end
|
159
|
+
value = hash
|
160
|
+
end
|
161
|
+
|
162
|
+
value.each do |name, item|
|
163
|
+
if name.is_a? Fixnum
|
164
|
+
# This item has a numeric index. We expect to be an array with a name and a value.
|
165
|
+
unless item.is_a?(Hash) && item.key?('name')
|
166
|
+
raise ArgumentError, 'When passing an array to ->write with numeric indices, every item must be an array containing at least the "name" key'
|
167
|
+
end
|
168
|
+
|
169
|
+
attributes = item.key?('attributes') ? item['attributes'] : []
|
170
|
+
name = item['name']
|
171
|
+
item = item['value'] || []
|
172
|
+
elsif item.is_a?(Hash) && item.key?('value')
|
173
|
+
# This item has a text index. We expect to be an array with a value and optional attributes.
|
174
|
+
attributes = item.key?('attributes') ? item['attributes'] : []
|
175
|
+
item = item['value']
|
176
|
+
else
|
177
|
+
# If it's an array with text-indices, we expect every item's
|
178
|
+
# key to be an xml element name in clark notation.
|
179
|
+
# No attributes can be passed.
|
180
|
+
attributes = []
|
181
|
+
end
|
182
|
+
|
183
|
+
writer.start_element(name)
|
184
|
+
writer.write_attributes(attributes)
|
185
|
+
writer.write(item)
|
186
|
+
writer.end_element
|
187
|
+
end
|
188
|
+
else
|
189
|
+
raise ArgumentError, "The writer cannot serialize objects of type: #{value.class}"
|
190
|
+
end
|
191
|
+
end
|
192
|
+
end
|
193
|
+
end
|
194
|
+
end
|
data/lib/tilia/xml/service.rb
CHANGED
@@ -25,6 +25,32 @@ module Tilia
|
|
25
25
|
# @return [Hash]
|
26
26
|
attr_accessor :namespace_map
|
27
27
|
|
28
|
+
# This is a list of custom serializers for specific classes.
|
29
|
+
#
|
30
|
+
# The writer may use this if you attempt to serialize an object with a
|
31
|
+
# class that does not implement XmlSerializable.
|
32
|
+
#
|
33
|
+
# Instead it will look at this classmap to see if there is a custom
|
34
|
+
# serializer here. This is useful if you don't want your value objects
|
35
|
+
# to be responsible for serializing themselves.
|
36
|
+
#
|
37
|
+
# The keys in this classmap need to be fully qualified PHP class names,
|
38
|
+
# the values must be callbacks. The callbacks take two arguments. The
|
39
|
+
# writer class, and the value that must be written.
|
40
|
+
#
|
41
|
+
# function (Writer writer, object value)
|
42
|
+
#
|
43
|
+
# @return [Hash]
|
44
|
+
attr_accessor :class_map
|
45
|
+
|
46
|
+
# Initializes the xml service
|
47
|
+
def initialize
|
48
|
+
@element_map = {}
|
49
|
+
@namespace_map = {}
|
50
|
+
@class_map = {}
|
51
|
+
@value_object_map = {}
|
52
|
+
end
|
53
|
+
|
28
54
|
# Returns a fresh XML Reader
|
29
55
|
#
|
30
56
|
# @return [Reader]
|
@@ -40,6 +66,7 @@ module Tilia
|
|
40
66
|
def writer
|
41
67
|
writer = Writer.new
|
42
68
|
writer.namespace_map = @namespace_map
|
69
|
+
writer.class_map = @class_map
|
43
70
|
writer
|
44
71
|
end
|
45
72
|
|
@@ -57,7 +84,7 @@ module Tilia
|
|
57
84
|
#
|
58
85
|
# @param [String, File, StringIO] input
|
59
86
|
# @param [String, nil] context_uri
|
60
|
-
# @param [
|
87
|
+
# @param [Tilia::Box, nil] root_element_name
|
61
88
|
# @raise [ParseException]
|
62
89
|
# @return [Array, Object, String]
|
63
90
|
def parse(input, context_uri = nil, root_element_name = Box.new)
|
@@ -81,19 +108,20 @@ module Tilia
|
|
81
108
|
# This is useful in cases where you expected a specific document to be
|
82
109
|
# passed, and reduces the amount of if statements.
|
83
110
|
#
|
84
|
-
# @param [String] root_element_name
|
111
|
+
# @param [String, Array<String>] root_element_name
|
85
112
|
# @param [String, File, StringIO] input
|
86
113
|
# @param [String, nil] context_uri
|
87
114
|
# @return [void]
|
88
115
|
def expect(root_element_name, input, context_uri = nil)
|
89
|
-
|
116
|
+
root_element_name = [root_element_name] unless root_element_name.is_a?(Array)
|
117
|
+
|
90
118
|
reader = self.reader
|
91
119
|
reader.context_uri = context_uri
|
92
120
|
reader.xml(input)
|
93
121
|
|
94
122
|
result = reader.parse
|
95
|
-
|
96
|
-
|
123
|
+
unless root_element_name.include?(result['name'])
|
124
|
+
raise Tilia::Xml::ParseException, "Expected #{root_element_name.join(' or ')} but received #{result['name']} as the root element"
|
97
125
|
end
|
98
126
|
result['value']
|
99
127
|
end
|
@@ -125,6 +153,68 @@ module Tilia
|
|
125
153
|
writer.output_memory
|
126
154
|
end
|
127
155
|
|
156
|
+
# Map an xml element to a PHP class.
|
157
|
+
#
|
158
|
+
# Calling this function will automatically setup the Reader and Writer
|
159
|
+
# classes to turn a specific XML element to a PHP class.
|
160
|
+
#
|
161
|
+
# For example, given a class such as :
|
162
|
+
#
|
163
|
+
# class Author {
|
164
|
+
# public first_name
|
165
|
+
# public last_name
|
166
|
+
# }
|
167
|
+
#
|
168
|
+
# and an XML element such as:
|
169
|
+
#
|
170
|
+
# <author xmlns="http://example.org/ns">
|
171
|
+
# <firstName>...</firstName>
|
172
|
+
# <lastName>...</lastName>
|
173
|
+
# </author>
|
174
|
+
#
|
175
|
+
# These can easily be mapped by calling:
|
176
|
+
#
|
177
|
+
# service.map_value_object('{http://example.org}author', 'Author')
|
178
|
+
#
|
179
|
+
# @param [String] element_name
|
180
|
+
# @param [Class] klass
|
181
|
+
# @return [void]
|
182
|
+
def map_value_object(element_name, klass)
|
183
|
+
namespace = Service.parse_clark_notation(element_name).first
|
184
|
+
|
185
|
+
@element_map[element_name] = lambda do |reader|
|
186
|
+
return Deserializer.value_object(reader, klass, namespace)
|
187
|
+
end
|
188
|
+
@class_map[klass] = lambda do |writer, value_object|
|
189
|
+
return Serializer.value_object(writer, value_object, namespace)
|
190
|
+
end
|
191
|
+
@value_object_map[klass] = element_name
|
192
|
+
end
|
193
|
+
|
194
|
+
# Writes a value object.
|
195
|
+
#
|
196
|
+
# This function largely behaves similar to write, except that it's
|
197
|
+
# intended specifically to serialize a Value Object into an XML document.
|
198
|
+
#
|
199
|
+
# The ValueObject must have been previously registered using
|
200
|
+
# map_value_object.
|
201
|
+
#
|
202
|
+
# @param object
|
203
|
+
# @param [String] context_uri
|
204
|
+
# @return [void]
|
205
|
+
def write_value_object(object, context_uri = nil)
|
206
|
+
unless @value_object_map.key?(object.class)
|
207
|
+
raise ArgumentError,
|
208
|
+
"'#{object.class}' is not a registered value object class. Register your class with mapValueObject"
|
209
|
+
end
|
210
|
+
|
211
|
+
write(
|
212
|
+
@value_object_map[object.class],
|
213
|
+
object,
|
214
|
+
context_uri
|
215
|
+
)
|
216
|
+
end
|
217
|
+
|
128
218
|
# Parses a clark-notation string, and returns the namespace and element
|
129
219
|
# name components.
|
130
220
|
#
|
@@ -132,20 +222,14 @@ module Tilia
|
|
132
222
|
#
|
133
223
|
# @param [String] str
|
134
224
|
# @raise [InvalidArgumentException]
|
135
|
-
# @return [Array]
|
225
|
+
# @return [Array(String, String)]
|
136
226
|
def self.parse_clark_notation(str)
|
137
227
|
if str =~ /^{([^}]*)}(.*)/
|
138
|
-
[Regexp.last_match[1], Regexp.last_match[2]]
|
228
|
+
[Regexp.last_match[1] || '', Regexp.last_match[2]]
|
139
229
|
else
|
140
|
-
|
230
|
+
raise ArgumentError, "'#{str}' is not a valid clark-notation formatted string"
|
141
231
|
end
|
142
232
|
end
|
143
|
-
|
144
|
-
# TODO: document
|
145
|
-
def initialize
|
146
|
-
@element_map = {}
|
147
|
-
@namespace_map = {}
|
148
|
-
end
|
149
233
|
end
|
150
234
|
end
|
151
235
|
end
|
data/lib/tilia/xml/version.rb
CHANGED
data/lib/tilia/xml/writer.rb
CHANGED
@@ -22,27 +22,6 @@ module Tilia
|
|
22
22
|
class Writer
|
23
23
|
include ContextStackTrait
|
24
24
|
|
25
|
-
protected
|
26
|
-
|
27
|
-
# Any namespace that the writer is asked to write, will be added here.
|
28
|
-
#
|
29
|
-
# Any of these elements will get a new namespace definition *every single
|
30
|
-
# time* they are used, but this array allows the writer to make sure that
|
31
|
-
# the prefixes are consistent anyway.
|
32
|
-
#
|
33
|
-
# @return [Hash]
|
34
|
-
attr_accessor :adhoc_namespaces
|
35
|
-
|
36
|
-
# When the first element is written, this flag is set to true.
|
37
|
-
#
|
38
|
-
# This ensures that the namespaces in the namespaces map are only written
|
39
|
-
# once.
|
40
|
-
#
|
41
|
-
# @return [Boolean]
|
42
|
-
attr_accessor :namespaces_written
|
43
|
-
|
44
|
-
public
|
45
|
-
|
46
25
|
# Writes a value to the output stream.
|
47
26
|
#
|
48
27
|
# The following values are supported:
|
@@ -84,53 +63,7 @@ module Tilia
|
|
84
63
|
# @param value
|
85
64
|
# @return [void]
|
86
65
|
def write(value)
|
87
|
-
|
88
|
-
write_string(value.to_s)
|
89
|
-
elsif value.is_a?(TrueClass) || value.is_a?(FalseClass)
|
90
|
-
write_string(value.to_s)
|
91
|
-
elsif value.is_a? XmlSerializable
|
92
|
-
value.xml_serialize(self)
|
93
|
-
elsif value.nil?
|
94
|
-
# noop
|
95
|
-
elsif value.is_a?(Hash) || value.is_a?(Array)
|
96
|
-
# Code for ruby implementation
|
97
|
-
if value.is_a?(Array)
|
98
|
-
hash = {}
|
99
|
-
value.each_with_index do |v, i|
|
100
|
-
hash[i] = v
|
101
|
-
end
|
102
|
-
value = hash
|
103
|
-
end
|
104
|
-
|
105
|
-
value.each do |name, item|
|
106
|
-
if name.is_a? Fixnum
|
107
|
-
# This item has a numeric index. We expect to be an array with a name and a value.
|
108
|
-
unless item.is_a?(Hash) && item.key?('name') && item.key?('value')
|
109
|
-
fail ArgumentError, 'When passing an array to ->write with numeric indices, every item must be an array containing the "name" and "value" key'
|
110
|
-
end
|
111
|
-
|
112
|
-
attributes = item.key?('attributes') ? item['attributes'] : []
|
113
|
-
name = item['name']
|
114
|
-
item = item['value']
|
115
|
-
elsif item.is_a?(Hash) && item.key?('value')
|
116
|
-
# This item has a text index. We expect to be an array with a value and optional attributes.
|
117
|
-
attributes = item.key?('attributes') ? item['attributes'] : []
|
118
|
-
item = item['value']
|
119
|
-
else
|
120
|
-
# If it's an array with text-indices, we expect every item's
|
121
|
-
# key to be an xml element name in clark notation.
|
122
|
-
# No attributes can be passed.
|
123
|
-
attributes = []
|
124
|
-
end
|
125
|
-
|
126
|
-
start_element(name)
|
127
|
-
write_attributes(attributes)
|
128
|
-
write(item)
|
129
|
-
end_element
|
130
|
-
end
|
131
|
-
else
|
132
|
-
fail ArgumentError, "The writer cannot serialize objects of type: #{value.class}"
|
133
|
-
end
|
66
|
+
Serializer.standard_serializer(self, value)
|
134
67
|
end
|
135
68
|
|
136
69
|
# Starts an element.
|
@@ -141,20 +74,20 @@ module Tilia
|
|
141
74
|
if name[0] == '{'
|
142
75
|
(namespace, local_name) = Service.parse_clark_notation(name)
|
143
76
|
|
144
|
-
if @namespace_map.key?
|
145
|
-
|
146
|
-
|
77
|
+
if @namespace_map.key?(namespace)
|
78
|
+
tmp_ns = @namespace_map[namespace]
|
79
|
+
tmp_ns = nil if tmp_ns.blank?
|
80
|
+
result = start_element_ns(tmp_ns, local_name, nil)
|
81
|
+
elsif namespace.blank?
|
147
82
|
# An empty namespace means it's the global namespace. This is
|
148
83
|
# allowed, but it mustn't get a prefix.
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
@adhoc_namespaces[namespace] = 'x' + (@adhoc_namespaces.size + 1).to_s
|
155
|
-
end
|
156
|
-
result = start_element_ns(@adhoc_namespaces[namespace], local_name, namespace)
|
84
|
+
result = start_element(local_name)
|
85
|
+
write_attribute('xmlns', '')
|
86
|
+
else
|
87
|
+
unless @adhoc_namespaces.key?(namespace)
|
88
|
+
@adhoc_namespaces[namespace] = 'x' + (@adhoc_namespaces.size + 1).to_s
|
157
89
|
end
|
90
|
+
result = start_element_ns(@adhoc_namespaces[namespace], local_name, namespace)
|
158
91
|
end
|
159
92
|
else
|
160
93
|
result = @writer.start_element(name)
|
@@ -162,7 +95,7 @@ module Tilia
|
|
162
95
|
|
163
96
|
unless @namespaces_written
|
164
97
|
@namespace_map.each do |ns, prefix|
|
165
|
-
write_attribute((prefix ? 'xmlns:' + prefix : 'xmlns'), ns)
|
98
|
+
write_attribute((prefix.present? ? 'xmlns:' + prefix : 'xmlns'), ns)
|
166
99
|
end
|
167
100
|
@namespaces_written = true
|
168
101
|
end
|
@@ -170,10 +103,24 @@ module Tilia
|
|
170
103
|
result
|
171
104
|
end
|
172
105
|
|
173
|
-
# Write a full element tag.
|
106
|
+
# Write a full element tag and it's contents.
|
174
107
|
#
|
175
108
|
# This method automatically closes the element as well.
|
176
109
|
#
|
110
|
+
# The element name may be specified in clark-notation.
|
111
|
+
#
|
112
|
+
# Examples:
|
113
|
+
#
|
114
|
+
# writer.write_element('{http://www.w3.org/2005/Atom}author',null)
|
115
|
+
# becomes:
|
116
|
+
# <author xmlns="http://www.w3.org/2005" />
|
117
|
+
#
|
118
|
+
# writer.write_element('{http://www.w3.org/2005/Atom}author', [
|
119
|
+
# '{http://www.w3.org/2005/Atom}name' => 'Evert Pot',
|
120
|
+
# ])
|
121
|
+
# becomes:
|
122
|
+
# <author xmlns="http://www.w3.org/2005" /><name>Evert Pot</name></author>
|
123
|
+
#
|
177
124
|
# @param [String] name
|
178
125
|
# @param [String] content
|
179
126
|
# @return [Boolean]
|
@@ -211,7 +158,7 @@ module Tilia
|
|
211
158
|
def write_attribute(name, value)
|
212
159
|
if name[0] == '{'
|
213
160
|
(namespace, local_name) = Service.parse_clark_notation(name)
|
214
|
-
if @namespace_map.key?
|
161
|
+
if @namespace_map.key?(namespace)
|
215
162
|
# It's an attribute with a namespace we know
|
216
163
|
write_attribute(
|
217
164
|
@namespace_map[namespace] + ':' + local_name,
|
@@ -233,26 +180,33 @@ module Tilia
|
|
233
180
|
end
|
234
181
|
end
|
235
182
|
|
236
|
-
#
|
183
|
+
# Initializes the instance variables
|
237
184
|
def initialize
|
238
185
|
@adhoc_namespaces = {}
|
239
186
|
@namespaces_written = false
|
240
|
-
|
187
|
+
|
188
|
+
super
|
241
189
|
end
|
242
190
|
|
243
|
-
#
|
191
|
+
# Fakes the php function open_memory
|
192
|
+
#
|
193
|
+
# Initilizes the LibXML Writer
|
194
|
+
#
|
195
|
+
# @return [void]
|
244
196
|
def open_memory
|
245
|
-
|
197
|
+
raise 'XML document already created' if @writer
|
246
198
|
|
247
199
|
@writer = ::LibXML::XML::Writer.string
|
248
200
|
end
|
249
201
|
|
250
|
-
#
|
202
|
+
# Fakes the php function output_memory
|
203
|
+
#
|
204
|
+
# @return [String]
|
251
205
|
def output_memory
|
252
206
|
@writer.result
|
253
207
|
end
|
254
208
|
|
255
|
-
#
|
209
|
+
# Delegates missing methods to XML::Writer instance
|
256
210
|
def method_missing(name, *args)
|
257
211
|
@writer.send(name, *args)
|
258
212
|
end
|