Module: Tilia::Xml::Serializer
- Defined in:
- lib/tilia/xml/serializer.rb
Overview
This file provides a number of ‘serializer’ helper functions.
These helper functions can be used to easily xml-encode common PHP data structures, or can be placed in the class_map.
Class Method Summary collapse
-
.enum(writer, values) ⇒ void
The ‘enum’ serializer writes simple list of elements.
-
.repeating_elements(writer, items, child_element_name) ⇒ void
This serializer helps you serialize xml structures that look like this:.
-
.standard_serializer(writer, value) ⇒ void
This function is the ‘default’ serializer that is able to serialize most things, and delegates to other serializers if needed.
-
.value_object(writer, value_object, namespace) ⇒ Object
The valueObject serializer turns a simple PHP object into a classname.
Class Method Details
.enum(writer, values) ⇒ void
This method returns an undefined value.
The ‘enum’ serializer writes simple list of elements.
For example, calling:
enum(writer, [
"{http://sabredav.org/ns}elem1",
"{http://sabredav.org/ns}elem2",
"{http://sabredav.org/ns}elem3",
"{http://sabredav.org/ns}elem4",
"{http://sabredav.org/ns}elem5",
])
Will generate something like this (if the correct namespace is declared):
<s:elem1 /> <s:elem2 /> <s:elem3 /> <s:elem4>content</s:elem4> <s:elem5 attr=“val” />
31 32 33 34 35 |
# File 'lib/tilia/xml/serializer.rb', line 31 def self.enum(writer, values) values.each do |value| writer.write_element(value) end end |
.repeating_elements(writer, items, child_element_name) ⇒ void
This method returns an undefined value.
This serializer helps you serialize xml structures that look like this:
<collection>
<item>...</item>
<item>...</item>
<item>...</item>
</collection>
In that previous example, this serializer just serializes the item element, and this could be called like this:
repeating_elements(writer, items, ‘{}item’)
74 75 76 77 78 |
# File 'lib/tilia/xml/serializer.rb', line 74 def self.repeating_elements(writer, items, child_element_name) items.each do |item| writer.write_element(child_element_name, item) end end |
.standard_serializer(writer, value) ⇒ void
This method returns an undefined value.
This function is the ‘default’ serializer that is able to serialize most things, and delegates to other serializers if needed.
The standardSerializer supports a wide-array of values.
value may be a string or integer, it will just write out the string as text. value may be an instance of XmlSerializable or Element, in which case it
calls it's xml_serialize method.
value may be a PHP callback/function/closure, in case we call the callback
and give it the Writer as an argument.
value may be a an object, and if it’s in the classMap we automatically call
the correct serializer for it.
value may be null, in which case we do nothing.
If value is an array, the array must look like this:
[
[
'name' => '{namespaceUri}element-name',
'value' => '...',
'attributes' => [ 'attName' => 'attValue' ]
]
[,
'name' => '{namespaceUri}element-name2',
'value' => '...',
]
]
This would result in xml like:
<element-name xmlns=“namespaceUri” attName=“attValue”>
...
</element-name> <element-name2>
...
</element-name2>
The value property may be any value standardSerializer supports, so you can nest data-structures this way. Both value and attributes are optional.
Alternatively, you can also specify the array using this syntax:
[
[
'{namespaceUri}element-name' => '...',
'{namespaceUri}element-name2' => '...',
]
]
This is excellent for simple key.value structures, and here you can also specify anything for the value.
You can even mix the two array syntaxes.
137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 |
# File 'lib/tilia/xml/serializer.rb', line 137 def self.standard_serializer(writer, value) if value.is_a?(Numeric) || value.is_a?(String) writer.write_string(value.to_s) elsif value.is_a?(TrueClass) || value.is_a?(FalseClass) writer.write_string(value.to_s) elsif value.is_a?(XmlSerializable) value.xml_serialize(writer) elsif writer.class_map.key?(value.class) # It's an object which class appears in the classmap. writer.class_map[value.class].call(writer, value) elsif value.respond_to?(:call) # A callback value.call(writer) elsif value.nil? # noop elsif value.is_a?(Hash) || value.is_a?(Array) # Code for ruby implementation if value.is_a?(Array) hash = {} value.each_with_index do |v, i| hash[i] = v end value = hash end value.each do |name, item| if name.is_a? Fixnum # This item has a numeric index. We expect to be an array with a name and a value. unless item.is_a?(Hash) && item.key?('name') raise ArgumentError, 'When passing an array to ->write with numeric indices, every item must be an array containing at least the "name" key' end attributes = item.key?('attributes') ? item['attributes'] : [] name = item['name'] item = item['value'] || [] elsif item.is_a?(Hash) && item.key?('value') # This item has a text index. We expect to be an array with a value and optional attributes. attributes = item.key?('attributes') ? item['attributes'] : [] item = item['value'] else # If it's an array with text-indices, we expect every item's # key to be an xml element name in clark notation. # No attributes can be passed. attributes = [] end writer.start_element(name) writer.write_attributes(attributes) writer.write(item) writer.end_element end else raise ArgumentError, "The writer cannot serialize objects of type: #{value.class}" end end |
.value_object(writer, value_object, namespace) ⇒ Object
The valueObject serializer turns a simple PHP object into a classname.
Every public property will be encoded as an xml element with the same name, in the XML namespace as specified.
45 46 47 48 49 50 51 52 53 54 |
# File 'lib/tilia/xml/serializer.rb', line 45 def self.value_object(writer, value_object, namespace) value_object.instance_variables.each do |key| value = value_object.instance_variable_get(key) # key is a symbol and starts with @ key = key.to_s[1..-1] writer.write_element("{#{namespace}}#{key}", value) end end |