3586b24a6b99330be44ec79f9f1613dde96700a9
[feedcatcher.git] / vendor / rails / activesupport / lib / active_support / xml_mini / libxml.rb
1 require 'libxml'
2
3 # = XmlMini LibXML implementation
4 module ActiveSupport
5 module XmlMini_LibXML #:nodoc:
6 extend self
7
8 # Parse an XML Document string into a simple hash using libxml.
9 # string::
10 # XML Document string to parse
11 def parse(string)
12 LibXML::XML.default_keep_blanks = false
13
14 if string.blank?
15 {}
16 else
17 LibXML::XML::Parser.string(string.strip).parse.to_hash
18 end
19 end
20
21 end
22 end
23
24 module LibXML
25 module Conversions
26 module Document
27 def to_hash
28 root.to_hash
29 end
30 end
31
32 module Node
33 CONTENT_ROOT = '__content__'
34 LIB_XML_LIMIT = 30000000 # Hardcoded LibXML limit
35
36 # Convert XML document to hash
37 #
38 # hash::
39 # Hash to merge the converted element into.
40 def to_hash(hash={})
41 if text?
42 raise LibXML::XML::Error if content.length >= LIB_XML_LIMIT
43 hash[CONTENT_ROOT] = content
44 else
45 sub_hash = insert_name_into_hash(hash, name)
46 attributes_to_hash(sub_hash)
47 if array?
48 children_array_to_hash(sub_hash)
49 elsif yaml?
50 children_yaml_to_hash(sub_hash)
51 else
52 children_to_hash(sub_hash)
53 end
54 end
55 hash
56 end
57
58 protected
59
60 # Insert name into hash
61 #
62 # hash::
63 # Hash to merge the converted element into.
64 # name::
65 # name to to merge into hash
66 def insert_name_into_hash(hash, name)
67 sub_hash = {}
68 if hash[name]
69 if !hash[name].kind_of? Array
70 hash[name] = [hash[name]]
71 end
72 hash[name] << sub_hash
73 else
74 hash[name] = sub_hash
75 end
76 sub_hash
77 end
78
79 # Insert children into hash
80 #
81 # hash::
82 # Hash to merge the children into.
83 def children_to_hash(hash={})
84 each { |child| child.to_hash(hash) }
85 attributes_to_hash(hash)
86 hash
87 end
88
89 # Convert xml attributes to hash
90 #
91 # hash::
92 # Hash to merge the attributes into
93 def attributes_to_hash(hash={})
94 each_attr { |attr| hash[attr.name] = attr.value }
95 hash
96 end
97
98 # Convert array into hash
99 #
100 # hash::
101 # Hash to merge the array into
102 def children_array_to_hash(hash={})
103 hash[child.name] = map do |child|
104 returning({}) { |sub_hash| child.children_to_hash(sub_hash) }
105 end
106 hash
107 end
108
109 # Convert yaml into hash
110 #
111 # hash::
112 # Hash to merge the yaml into
113 def children_yaml_to_hash(hash = {})
114 hash[CONTENT_ROOT] = content unless content.blank?
115 hash
116 end
117
118 # Check if child is of type array
119 def array?
120 child? && child.next? && child.name == child.next.name
121 end
122
123 # Check if child is of type yaml
124 def yaml?
125 attributes.collect{|x| x.value}.include?('yaml')
126 end
127
128 end
129 end
130 end
131
132 LibXML::XML::Document.send(:include, LibXML::Conversions::Document)
133 LibXML::XML::Node.send(:include, LibXML::Conversions::Node)