summaryrefslogtreecommitdiff
blob: 51867ef82b922b17c221a8b6e7eba9f6dc8d0373 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
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
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
Index: lib/rexml/parsers/baseparser.rb
===================================================================
--- lib/rexml/parsers/baseparser.rb	(revision 13599)
+++ lib/rexml/parsers/baseparser.rb	(revision 13600)
@@ -1,5 +1,6 @@
 require 'rexml/parseexception'
 require 'rexml/source'
+require 'set'
 
 module REXML
   module Parsers
@@ -24,7 +25,8 @@
     # Nat Price gave me some good ideas for the API.
     class BaseParser
       NCNAME_STR= '[\w:][\-\w\d.]*'
-      NAME_STR= "(?:#{NCNAME_STR}:)?#{NCNAME_STR}"
+      NAME_STR= "(?:(#{NCNAME_STR}):)?(#{NCNAME_STR})"
+      UNAME_STR= "(?:#{NCNAME_STR}:)?#{NCNAME_STR}"
 
       NAMECHAR = '[\-\w\d\.:]'
       NAME = "([\\w:]#{NAMECHAR}*)"
@@ -35,7 +37,7 @@
 
       DOCTYPE_START = /\A\s*<!DOCTYPE\s/um
       DOCTYPE_PATTERN = /\s*<!DOCTYPE\s+(.*?)(\[|>)/um
-      ATTRIBUTE_PATTERN = /\s*(#{NAME_STR})\s*=\s*(["'])(.*?)\2/um
+      ATTRIBUTE_PATTERN = /\s*(#{NAME_STR})\s*=\s*(["'])(.*?)\4/um
       COMMENT_START = /\A<!--/u
       COMMENT_PATTERN = /<!--(.*?)-->/um
       CDATA_START = /\A<!\[CDATA\[/u
@@ -45,7 +47,7 @@
       XMLDECL_PATTERN = /<\?xml\s+(.*?)\?>/um
       INSTRUCTION_START = /\A<\?/u
       INSTRUCTION_PATTERN = /<\?(.*?)(\s+.*?)?\?>/um
-      TAG_MATCH = /^<((?>#{NAME_STR}))\s*((?>\s+#{NAME_STR}\s*=\s*(["']).*?\3)*)\s*(\/)?>/um
+      TAG_MATCH = /^<((?>#{NAME_STR}))\s*((?>\s+#{UNAME_STR}\s*=\s*(["']).*?\5)*)\s*(\/)?>/um
       CLOSE_MATCH = /^\s*<\/(#{NAME_STR})\s*>/um
 
       VERSION = /\bversion\s*=\s*["'](.*?)['"]/um
@@ -133,6 +135,7 @@
         @tags = []
         @stack = []
         @entities = []
+        @nsstack = []
       end
 
       def position
@@ -213,6 +216,7 @@
             return [ :processing_instruction, *@source.match(INSTRUCTION_PATTERN, true)[1,2] ]
           when DOCTYPE_START
             md = @source.match( DOCTYPE_PATTERN, true )
+            @nsstack.unshift(curr_ns=Set.new)
             identity = md[1]
             close = md[2]
             identity =~ IDENTITY
@@ -288,6 +292,9 @@
                 val = attdef[3]
                 val = attdef[4] if val == "#FIXED "
                 pairs[attdef[0]] = val
+                if attdef[0] =~ /^xmlns:(.*)/
+                  @nsstack[0] << $1
+                end
               end
             end
             return [ :attlistdecl, element, pairs, contents ]
@@ -312,6 +319,7 @@
         begin
           if @source.buffer[0] == ?<
             if @source.buffer[1] == ?/
+              @nsstack.shift
               last_tag = @tags.pop
               #md = @source.match_to_consume( '>', CLOSE_MATCH)
               md = @source.match( CLOSE_MATCH, true )
@@ -345,19 +353,47 @@
                 raise REXML::ParseException.new("missing attribute quote", @source) if @source.match(MISSING_ATTRIBUTE_QUOTES )
                 raise REXML::ParseException.new("malformed XML: missing tag start", @source) 
               end
-              attrs = []
-              if md[2].size > 0
-                attrs = md[2].scan( ATTRIBUTE_PATTERN )
+              attributes = {}
+              prefixes = Set.new
+              prefixes << md[2] if md[2]
+              @nsstack.unshift(curr_ns=Set.new)
+              if md[4].size > 0
+                attrs = md[4].scan( ATTRIBUTE_PATTERN )
                 raise REXML::ParseException.new( "error parsing attributes: [#{attrs.join ', '}], excess = \"#$'\"", @source) if $' and $'.strip.size > 0
+                attrs.each { |a,b,c,d,e| 
+                  if b == "xmlns"
+                    if c == "xml"
+                      if d != "http://www.w3.org/XML/1998/namespace"
+                        msg = "The 'xml' prefix must not be bound to any other namespace "+
+                        "(http://www.w3.org/TR/REC-xml-names/#ns-decl)"
+                        raise REXML::ParseException.new( msg, @source, self )
+                      end
+                    elsif c == "xmlns"
+                      msg = "The 'xmlns' prefix must not be declared "+
+                      "(http://www.w3.org/TR/REC-xml-names/#ns-decl)"
+                      raise REXML::ParseException.new( msg, @source, self)
+                    end
+                    curr_ns << c
+                  elsif b
+                    prefixes << b unless b == "xml"
+                  end
+                  attributes[a] = e 
+                }
               end
         
-              if md[4]
+              # Verify that all of the prefixes have been defined
+              for prefix in prefixes
+                unless @nsstack.find{|k| k.member?(prefix)}
+                  raise UndefinedNamespaceException.new(prefix,@source,self)
+                end
+              end
+
+              if md[6]
                 @closed = md[1]
+                @nsstack.shift
               else
                 @tags.push( md[1] )
               end
-              attributes = {}
-              attrs.each { |a,b,c| attributes[a] = c }
               return [ :start_element, md[1], attributes ]
             end
           else
@@ -371,6 +407,8 @@
             # return PullEvent.new( :text, md[1], unnormalized )
             return [ :text, md[1] ]
           end
+        rescue REXML::UndefinedNamespaceException
+          raise
         rescue REXML::ParseException
           raise
         rescue Exception, NameError => error
Index: lib/rexml/parsers/treeparser.rb
===================================================================
--- lib/rexml/parsers/treeparser.rb	(revision 13599)
+++ lib/rexml/parsers/treeparser.rb	(revision 13600)
@@ -29,8 +29,7 @@
               return
             when :start_element
               tag_stack.push(event[1])
-              # find the observers for namespaces
-              @build_context = @build_context.add_element( event[1], event[2] )
+              el = @build_context = @build_context.add_element( event[1], event[2] )
             when :end_element
               tag_stack.pop
               @build_context = @build_context.parent
@@ -86,6 +85,8 @@
           end
         rescue REXML::Validation::ValidationException
           raise
+        rescue REXML::UndefinedNamespaceException
+          raise
         rescue
           raise ParseException.new( $!.message, @parser.source, @parser, $! )
         end
Index: lib/rexml/document.rb
===================================================================
--- lib/rexml/document.rb	(revision 13599)
+++ lib/rexml/document.rb	(revision 13600)
@@ -66,6 +66,7 @@
 		def add( child )
 			if child.kind_of? XMLDecl
 				@children.unshift child
+        child.parent = self
 			elsif child.kind_of? DocType
         # Find first Element or DocType node and insert the decl right 
         # before it.  If there is no such node, just insert the child at the
@@ -183,7 +184,7 @@
         output = Output.new( output, xml_decl.encoding )
       end
       formatter = if indent > -1
-          if transitive
+          if trans
             REXML::Formatters::Transitive.new( indent, ie_hack )
           else
             REXML::Formatters::Pretty.new( indent, ie_hack )
Index: lib/rexml/element.rb
===================================================================
--- lib/rexml/element.rb	(revision 13599)
+++ lib/rexml/element.rb	(revision 13600)
@@ -553,6 +553,7 @@
     def attribute( name, namespace=nil )
       prefix = nil
       prefix = namespaces.index(namespace) if namespace
+      prefix = nil if prefix == 'xmlns'
       attributes.get_attribute( "#{prefix ? prefix + ':' : ''}#{name}" )
     end
 
@@ -854,15 +855,15 @@
     #   Source (see Element.initialize).  If not supplied or nil, a
     #   new, default Element will be constructed
     # Returns:: the added Element
-    #  a = Element.new 'a'
-    #  a.elements.add Element.new 'b'  #-> <a><b/></a>
-    #  a.elements.add 'c'              #-> <a><b/><c/></a>
+    #  a = Element.new('a')
+    #  a.elements.add(Element.new('b'))  #-> <a><b/></a>
+    #  a.elements.add('c')               #-> <a><b/><c/></a>
     def add element=nil
       rv = nil
       if element.nil?
-        Element.new "", self, @element.context
+        Element.new("", self, @element.context)
       elsif not element.kind_of?(Element)
-        Element.new element, self, @element.context
+        Element.new(element, self, @element.context)
       else
         @element << element
         element.context = @element.context
Index: lib/rexml/undefinednamespaceexception.rb
===================================================================
--- lib/rexml/undefinednamespaceexception.rb	(revision 0)
+++ lib/rexml/undefinednamespaceexception.rb	(revision 13600)
@@ -0,0 +1,8 @@
+require 'rexml/parseexception'
+module REXML
+  class UndefinedNamespaceException < ParseException
+    def initialize( prefix, source, parser )
+      super( "Undefined prefix #{prefix} found" )
+    end
+  end
+end
Index: lib/rexml/source.rb
===================================================================
--- lib/rexml/source.rb	(revision 13599)
+++ lib/rexml/source.rb	(revision 13600)
@@ -17,8 +17,8 @@
       elsif arg.kind_of? Source
         arg
       else
-        raise "#{source.class} is not a valid input stream.  It must walk \n"+
-        "like either a String, IO, or Source."
+        raise "#{arg.class} is not a valid input stream.  It must walk \n"+
+          "like either a String, an IO, or a Source."
       end
     end
   end
Index: lib/rexml/attribute.rb
===================================================================
--- lib/rexml/attribute.rb	(revision 13599)
+++ lib/rexml/attribute.rb	(revision 13600)
@@ -50,7 +50,7 @@
 					@element = first.element
 				end
 			elsif first.kind_of? String
-				@element = parent if parent.kind_of? Element
+				@element = parent
 				self.name = first
 				@normalized = second.to_s
 			else
Index: lib/rexml/rexml.rb
===================================================================
--- lib/rexml/rexml.rb	(revision 13599)
+++ lib/rexml/rexml.rb	(revision 13600)
@@ -1,3 +1,4 @@
+# -*- encoding: utf-8 -*-
 # REXML is an XML toolkit for Ruby[http://www.ruby-lang.org], in Ruby.
 #
 # REXML is a _pure_ Ruby, XML 1.0 conforming,
@@ -10,8 +11,9 @@
 #
 # Main page:: http://www.germane-software.com/software/rexml
 # Author:: Sean Russell <serATgermaneHYPHENsoftwareDOTcom>
-# Version:: 3.1.7.1
-# Date:: 2007/209
+# Version:: 3.1.7.2
+# Date:: 2007/275
+# Revision:: $Revision$
 # 
 # This API documentation can be downloaded from the REXML home page, or can
 # be accessed online[http://www.germane-software.com/software/rexml_doc]
@@ -20,10 +22,10 @@
 # or can be accessed 
 # online[http://www.germane-software.com/software/rexml/docs/tutorial.html]
 module REXML
-  COPYRIGHT = "Copyright © 2001-2007 Sean Russell <ser@germane-software.com>"
-  DATE = "2007/209"
-  VERSION = "3.1.7.1"
-  REVISION = "$Revision: 1270$".gsub(/\$Revision:|\$/,'').strip
+  COPYRIGHT = "Copyright \xC2\xA9 2001-2006 Sean Russell <ser@germane-software.com>"
+  VERSION = "3.1.7.2"
+  DATE = "2007/275"
+  REVISION = "$Revision$".gsub(/\$Revision:|\$/,'').strip
 
   Copyright = COPYRIGHT
   Version = VERSION

Property changes on: lib/rexml/dtd/dtd.rb
___________________________________________________________________
Name: svk:merge
   + 3a3bbbf4-582e-0410-a78b-8bf2211dae1f:/local/ruby-trunk/dtd/dtd.rb:1298


Property changes on: lib/rexml
___________________________________________________________________
Name: svk:merge
   - 3a3bbbf4-582e-0410-a78b-8bf2211dae1f:/local/rexml-trunk/src/rexml:1287
3a3bbbf4-582e-0410-a78b-8bf2211dae1f:/local/ruby-1.8.6:1339
3a3bbbf4-582e-0410-a78b-8bf2211dae1f:/local/ruby-trunk:1335
877f57f0-f5bd-0310-8c13-bb9e5bdefd87:/branches/3.1.7/src/rexml:1274
b2dd03c8-39d4-4d8f-98ff-823fe69b080e:/trunk/lib/rexml:12517
   + 3a3bbbf4-582e-0410-a78b-8bf2211dae1f:/local/rexml-trunk/src/rexml:1287
3a3bbbf4-582e-0410-a78b-8bf2211dae1f:/local/rexml/trunk/src/rexml:1404
3a3bbbf4-582e-0410-a78b-8bf2211dae1f:/local/ruby-1.8.6:1425
3a3bbbf4-582e-0410-a78b-8bf2211dae1f:/local/ruby-trunk:1380
877f57f0-f5bd-0310-8c13-bb9e5bdefd87:/branches/3.1.7/src/rexml:1274
b2dd03c8-39d4-4d8f-98ff-823fe69b080e:/trunk/lib/rexml:13097