flowplayer flash flv no longer work, move to mp4
[booh] / lib / booh / rexml / light / node.rb
1 require 'booh/rexml/xmltokens'
2 require 'booh/rexml/light/node'
3
4 # [ :element, parent, name, attributes, children* ]
5         # a = Node.new
6         # a << "B"              # => <a>B</a>
7         # a.b                   # => <a>B<b/></a>
8         # a.b[1]                        # => <a>B<b/><b/><a>
9         # a.b[1]["x"] = "y"     # => <a>B<b/><b x="y"/></a>
10         # a.b[0].c              # => <a>B<b><c/></b><b x="y"/></a>
11         # a.b.c << "D"          # => <a>B<b><c>D</c></b><b x="y"/></a>
12 module REXML
13         module Light
14                 # Represents a tagged XML element.  Elements are characterized by
15                 # having children, attributes, and names, and can themselves be
16                 # children.
17                 class Node
18                         NAMESPLIT = /^(?:(#{XMLTokens::NCNAME_STR}):)?(#{XMLTokens::NCNAME_STR})/u
19                         PARENTS = [ :element, :document, :doctype ]
20                         # Create a new element.
21                         def initialize node=nil
22                                 @node = node
23                                 if node.kind_of? String
24                                         node = [ :text, node ]
25                                 elsif node.nil?
26                                         node = [ :document, nil, nil ]
27                                 elsif node[0] == :start_element
28                                         node[0] = :element
29                                 elsif node[0] == :start_doctype
30                                         node[0] = :doctype
31                                 elsif node[0] == :start_document
32                                         node[0] = :document
33                                 end
34                         end
35
36                         def size
37                                 if PARENTS.include? @node[0]
38                                         @node[-1].size
39                                 else
40                                         0
41                                 end
42                         end
43
44                         def each( &block )
45                                 size.times { |x| yield( at(x+4) ) }
46                         end
47
48                         def name
49                                 at(2)
50                         end
51
52                         def name=( name_str, ns=nil )
53                                 pfx = ''
54                                 pfx = "#{prefix(ns)}:" if ns
55                                 _old_put(2, "#{pfx}#{name_str}")
56                         end
57
58                         def parent=( node )
59                                 _old_put(1,node)
60                         end
61
62                         def local_name
63                                 namesplit
64                                 @name
65                         end
66
67                         def local_name=( name_str )
68                                 _old_put( 1, "#@prefix:#{name_str}" )
69                         end
70
71                         def prefix( namespace=nil )
72                                 prefix_of( self, namespace )
73                         end
74
75                         def namespace( prefix=prefix() )
76                                 namespace_of( self, prefix )
77                         end
78
79                         def namespace=( namespace )
80                                 @prefix = prefix( namespace )
81                                 pfx = ''
82                                 pfx = "#@prefix:" if @prefix.size > 0
83                                 _old_put(1, "#{pfx}#@name")
84                         end
85
86                         def []( reference, ns=nil )
87                                 if reference.kind_of? String
88                                         pfx = ''
89                                         pfx = "#{prefix(ns)}:" if ns
90                                         at(3)["#{pfx}#{reference}"]
91                                 elsif reference.kind_of? Range
92                                         _old_get( Range.new(4+reference.begin, reference.end, reference.exclude_end?) )
93                                 else
94                                         _old_get( 4+reference )
95                                 end
96                         end
97
98                         def =~( path )
99                                 XPath.match( self, path )
100                         end
101
102                         # Doesn't handle namespaces yet
103                         def []=( reference, ns, value=nil )
104                                 if reference.kind_of? String
105                                         value = ns unless value
106                                         at( 3 )[reference] = value
107                                 elsif reference.kind_of? Range
108                                         _old_put( Range.new(3+reference.begin, reference.end, reference.exclude_end?), ns )
109                                 else
110                                         if value
111                                                 _old_put( 4+reference, ns, value )
112                                         else
113                                                 _old_put( 4+reference, ns )
114                                         end
115                                 end
116                         end
117
118                         # Append a child to this element, optionally under a provided namespace.
119                         # The namespace argument is ignored if the element argument is an Element
120                         # object.  Otherwise, the element argument is a string, the namespace (if
121                         # provided) is the namespace the element is created in.
122                         def << element
123                                 if node_type() == :text
124                                         at(-1) << element
125                                 else
126                                         newnode = Node.new( element )
127                                         newnode.parent = self
128                                         self.push( newnode )
129                                 end
130                                 at(-1)
131                         end
132
133                         def node_type
134                                 _old_get(0)
135                         end
136
137                         def text=( foo )
138                                 replace = at(4).kind_of?(String)? 1 : 0
139                                 self._old_put(4,replace, normalizefoo)
140                         end
141
142                         def root
143                                 context = self
144                                 context = context.at(1) while context.at(1)
145                         end
146
147                         def has_name?( name, namespace = '' )
148                                 at(3) == name and namespace() == namespace
149                         end
150
151                         def children
152                                 self
153                         end
154
155                         def parent
156                                 at(1)
157                         end
158
159                         def to_s
160
161                         end
162
163                         private
164
165                         def namesplit
166                                 return if @name.defined?
167                                 at(2) =~ NAMESPLIT
168                                 @prefix = '' || $1
169                                 @name = $2
170                         end
171
172                         def namespace_of( node, prefix=nil )
173                                 if not prefix
174                                         name = at(2)
175                                         name =~ NAMESPLIT
176                                         prefix = $1
177                                 end
178                                 to_find = 'xmlns'
179                                 to_find = "xmlns:#{prefix}" if not prefix.nil?
180                                 ns = at(3)[ to_find ]
181                                 ns ? ns : namespace_of( @node[0], prefix )
182                         end
183
184                         def prefix_of( node, namespace=nil )
185                                 if not namespace
186                                         name = node.name
187                                         name =~ NAMESPLIT
188                                         $1
189                                 else
190                                         ns = at(3).find { |k,v| v == namespace }
191                                         ns ? ns : prefix_of( node.parent, namespace )
192                                 end
193                         end
194                 end
195         end
196 end