~michaelforrest/use-case-mapper/trunk

« back to all changes in this revision

Viewing changes to vendor/rails/activesupport/lib/active_support/xml_mini/jdom.rb

  • Committer: Richard Lee (Canonical)
  • Date: 2010-10-15 15:17:58 UTC
  • mfrom: (190.1.3 use-case-mapper)
  • Revision ID: richard.lee@canonical.com-20101015151758-wcvmfxrexsongf9d
Merge

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
raise "JRuby is required to use the JDOM backend for XmlMini" unless RUBY_PLATFORM =~ /java/
2
 
 
3
 
require 'jruby'
4
 
include Java
5
 
 
6
 
import javax.xml.parsers.DocumentBuilder unless defined? DocumentBuilder
7
 
import javax.xml.parsers.DocumentBuilderFactory unless defined? DocumentBuilderFactory
8
 
import java.io.StringReader unless defined? StringReader
9
 
import org.xml.sax.InputSource unless defined? InputSource
10
 
import org.xml.sax.Attributes unless defined? Attributes
11
 
import org.w3c.dom.Node unless defined? Node
12
 
 
13
 
# = XmlMini JRuby JDOM implementation
14
 
module ActiveSupport
15
 
  module XmlMini_JDOM #:nodoc:
16
 
    extend self
17
 
 
18
 
    CONTENT_KEY = '__content__'.freeze
19
 
 
20
 
    NODE_TYPE_NAMES = %w{ATTRIBUTE_NODE CDATA_SECTION_NODE COMMENT_NODE DOCUMENT_FRAGMENT_NODE
21
 
    DOCUMENT_NODE DOCUMENT_TYPE_NODE ELEMENT_NODE ENTITY_NODE ENTITY_REFERENCE_NODE NOTATION_NODE
22
 
    PROCESSING_INSTRUCTION_NODE TEXT_NODE}
23
 
 
24
 
    node_type_map = {}
25
 
    NODE_TYPE_NAMES.each { |type| node_type_map[Node.send(type)] = type }
26
 
 
27
 
    # Parse an XML Document string into a simple hash using Java's jdom.
28
 
    # string::
29
 
    #   XML Document string to parse
30
 
    def parse(string)
31
 
      if string.blank?
32
 
        {}
33
 
      else
34
 
        @dbf = DocumentBuilderFactory.new_instance
35
 
        xml_string_reader = StringReader.new(string)
36
 
        xml_input_source = InputSource.new(xml_string_reader)
37
 
        doc = @dbf.new_document_builder.parse(xml_input_source)
38
 
        merge_element!({}, doc.document_element)
39
 
      end
40
 
    end
41
 
 
42
 
    private
43
 
 
44
 
    # Convert an XML element and merge into the hash
45
 
    #
46
 
    # hash::
47
 
    #   Hash to merge the converted element into.
48
 
    # element::
49
 
    #   XML element to merge into hash
50
 
    def merge_element!(hash, element)
51
 
      merge!(hash, element.tag_name, collapse(element))
52
 
    end
53
 
 
54
 
    # Actually converts an XML document element into a data structure.
55
 
    #
56
 
    # element::
57
 
    #   The document element to be collapsed.
58
 
    def collapse(element)
59
 
      hash = get_attributes(element)
60
 
 
61
 
      child_nodes = element.child_nodes
62
 
      if child_nodes.length > 0
63
 
        for i in 0...child_nodes.length
64
 
          child = child_nodes.item(i)
65
 
          merge_element!(hash, child) unless child.node_type == Node.TEXT_NODE
66
 
        end
67
 
        merge_texts!(hash, element) unless empty_content?(element)
68
 
        hash
69
 
      else
70
 
        merge_texts!(hash, element)
71
 
      end
72
 
    end
73
 
 
74
 
    # Merge all the texts of an element into the hash
75
 
    #
76
 
    # hash::
77
 
    #   Hash to add the converted emement to.
78
 
    # element::
79
 
    #   XML element whose texts are to me merged into the hash
80
 
    def merge_texts!(hash, element)
81
 
      text_children = texts(element)
82
 
      if text_children.join.empty?
83
 
        hash
84
 
      else
85
 
        # must use value to prevent double-escaping
86
 
        merge!(hash, CONTENT_KEY, text_children.join)
87
 
      end
88
 
    end
89
 
 
90
 
    # Adds a new key/value pair to an existing Hash. If the key to be added
91
 
    # already exists and the existing value associated with key is not
92
 
    # an Array, it will be wrapped in an Array. Then the new value is
93
 
    # appended to that Array.
94
 
    #
95
 
    # hash::
96
 
    #   Hash to add key/value pair to.
97
 
    # key::
98
 
    #   Key to be added.
99
 
    # value::
100
 
    #   Value to be associated with key.
101
 
    def merge!(hash, key, value)
102
 
      if hash.has_key?(key)
103
 
        if hash[key].instance_of?(Array)
104
 
          hash[key] << value
105
 
        else
106
 
          hash[key] = [hash[key], value]
107
 
        end
108
 
      elsif value.instance_of?(Array)
109
 
        hash[key] = [value]
110
 
      else
111
 
        hash[key] = value
112
 
      end
113
 
      hash
114
 
    end
115
 
 
116
 
    # Converts the attributes array of an XML element into a hash.
117
 
    # Returns an empty Hash if node has no attributes.
118
 
    #
119
 
    # element::
120
 
    #   XML element to extract attributes from.
121
 
    def get_attributes(element)
122
 
      attribute_hash = {}
123
 
      attributes = element.attributes
124
 
      for i in 0...attributes.length
125
 
         attribute_hash[attributes.item(i).name] =  attributes.item(i).value
126
 
       end
127
 
      attribute_hash
128
 
    end
129
 
 
130
 
    # Determines if a document element has text content
131
 
    #
132
 
    # element::
133
 
    #   XML element to be checked.
134
 
    def texts(element)
135
 
      texts = []
136
 
      child_nodes = element.child_nodes
137
 
      for i in 0...child_nodes.length
138
 
        item = child_nodes.item(i)
139
 
        if item.node_type == Node.TEXT_NODE
140
 
          texts << item.get_data
141
 
        end
142
 
      end
143
 
      texts
144
 
    end
145
 
 
146
 
    # Determines if a document element has text content
147
 
    #
148
 
    # element::
149
 
    #   XML element to be checked.
150
 
    def empty_content?(element)
151
 
      text = ''
152
 
      child_nodes = element.child_nodes
153
 
      for i in 0...child_nodes.length
154
 
        item = child_nodes.item(i)
155
 
        if item.node_type == Node.TEXT_NODE
156
 
          text << item.get_data.strip
157
 
        end
158
 
      end
159
 
      text.strip.length == 0
160
 
    end
161
 
  end
162
 
end