Module: HappyMapper
- Defined in:
- lib/happymapper.rb,
lib/happymapper/item.rb,
lib/happymapper/element.rb,
lib/happymapper/version.rb,
lib/happymapper/attribute.rb
Defined Under Namespace
Modules: ClassMethods Classes: Attribute, Element, Item
Constant Summary collapse
- DEFAULT_NS =
"happymapper"
- Version =
'0.4.0'
Class Method Summary collapse
Instance Method Summary collapse
-
#to_xml(parent_node = nil, default_namespace = nil) ⇒ Object
Create an xml representation of the specified class based on defined HappyMapper elements and attributes.
Class Method Details
.included(base) ⇒ Object
12 13 14 15 16 17 18 |
# File 'lib/happymapper.rb', line 12 def self.included(base) base.instance_variable_set("@attributes", {}) base.instance_variable_set("@elements", {}) base.instance_variable_set("@registered_namespaces", {}) base.extend ClassMethods end |
Instance Method Details
#to_xml(parent_node = nil, default_namespace = nil) ⇒ Object
Create an xml representation of the specified class based on defined HappyMapper elements and attributes. The method is defined in a way that it can be called recursively by classes that are also HappyMapper classes, allowg for the composition of classes.
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 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 |
# File 'lib/happymapper.rb', line 149 def to_xml(parent_node = nil, default_namespace = nil) # # Create a tag that uses the tag name of the class that has no contents # but has the specified namespace or uses the default namespace # current_node = XML::Node.new(self.class.tag_name) if parent_node # # if #to_xml has been called with a parent_node that means this method # is being called recursively (or a special case) and we want to return # the parent_node with the new node as a child # parent_node << current_node else # # If #to_xml has been called without a Node (and namespace) that # means we want to return an xml document # write_out_to_xml = true end # # Add all the registered namespaces to the current node and the current node's # root element. Without adding it to the root element it is not possible to # parse or use xpath to find elements. # if self.class.instance_variable_get('@registered_namespaces') # Given a node, continue moving up to parents until there are no more parents find_root_node = lambda {|node| while node.parent? ; node = node.parent ; end ; node } root_node = find_root_node.call(current_node) # Add the registered namespace to the found root node only if it does not already have one defined self.class.instance_variable_get('@registered_namespaces').each_pair do |prefix,href| XML::Namespace.new(current_node,prefix,href) XML::Namespace.new(root_node,prefix,href) unless root_node.namespaces.find_by_prefix(prefix) end end # # Determine the tag namespace if one has been specified. This value takes # precendence over one that is handed down to composed sub-classes. # tag_namespace = current_node.namespaces.find_by_prefix(self.class.namespace) || default_namespace # Set the namespace of the current node to the specified namespace current_node.namespaces.namespace = tag_namespace if tag_namespace # # Add all the attribute tags to the current node with their namespace, if one # is defined, or the namespace handed down to the node. # self.class.attributes.each do |attribute| attribute_namespace = current_node.namespaces.find_by_prefix(attribute.[:namespace]) || default_namespace value = send(attribute.method_name) # # If the attribute has a :on_save attribute defined that is a proc or # a defined method, then call those with the current value. # if on_save_operation = attribute.[:on_save] if on_save_operation.is_a?(Proc) value = on_save_operation.call(value) elsif respond_to?(on_save_operation) value = send(on_save_operation,value) end end current_node[ "#{attribute_namespace ? "#{attribute_namespace.prefix}:" : ""}#{attribute.tag}" ] = value end # # All all the elements defined (e.g. has_one, has_many, element) ... # self.class.elements.each do |element| tag = element.tag || element.name element_namespace = current_node.namespaces.find_by_prefix(element.[:namespace]) || tag_namespace value = send(element.name) # # If the element defines an :on_save lambda/proc then we will call that # operation on the specified value. This allows for operations to be # performed to convert the value to a specific value to be saved to the xml. # if on_save_operation = element.[:on_save] if on_save_operation.is_a?(Proc) value = on_save_operation.call(value) elsif respond_to?(on_save_operation) value = send(on_save_operation,value) end end # # Normally a nil value would be ignored, however if specified then # an empty element will be written to the xml # if value.nil? && element.[:state_when_nil] current_node << XML::Node.new(tag,nil,element_namespace) end # # To allow for us to treat both groups of items and singular items # equally we wrap the value and treat it as an array. # if value.nil? values = [] elsif value.respond_to?(:to_ary) && !element.[:single] values = value.to_ary else values = [value] end values.each do |item| if item.is_a?(HappyMapper) # # Other HappyMapper items that are convertable should not be called # with the current node and the namespace defined for the element. # item.to_xml(current_node,element_namespace) elsif item # # When a value exists we should append the value for the tag # current_node << XML::Node.new(tag,item.to_s,element_namespace) else # # Normally a nil value would be ignored, however if specified then # an empty element will be written to the xml # current_node << XML.Node.new(tag,nil,element_namespace) if element.[:state_when_nil] end end end # # Generate xml from a document if no node was passed as a parameter. Otherwise # this method is being called recursively (or special case) and we should # return the node with this node attached as a child. # if write_out_to_xml document = XML::Document.new document.root = current_node document.to_s else parent_node end end |