@@ -181,7 +181,8 @@ def stream=( source )
181181 @tags = [ ]
182182 @stack = [ ]
183183 @entities = [ ]
184- @nsstack = [ ]
184+ @namespaces = { }
185+ @namespaces_restore_stack = [ ]
185186 end
186187
187188 def position
@@ -285,7 +286,6 @@ def pull_event
285286 @source . position = start_position
286287 raise REXML ::ParseException . new ( message , @source )
287288 end
288- @nsstack . unshift ( Set . new )
289289 name = parse_name ( base_error_message )
290290 if @source . match ( /\s *\[ /um , true )
291291 id = [ nil , nil , nil ]
@@ -379,7 +379,7 @@ def pull_event
379379 val = attdef [ 4 ] if val == "#FIXED "
380380 pairs [ attdef [ 0 ] ] = val
381381 if attdef [ 0 ] =~ /^xmlns:(.*)/
382- @nsstack [ 0 ] << $1
382+ @namespaces [ $1 ] = val
383383 end
384384 end
385385 end
@@ -432,7 +432,7 @@ def pull_event
432432 # here explicitly.
433433 @source . ensure_buffer
434434 if @source . match ( "/" , true )
435- @nsstack . shift
435+ @namespaces_restore_stack . pop
436436 last_tag = @tags . pop
437437 md = @source . match ( Private ::CLOSE_PATTERN , true )
438438 if md and !last_tag
@@ -477,18 +477,18 @@ def pull_event
477477 @document_status = :in_element
478478 @prefixes . clear
479479 @prefixes << md [ 2 ] if md [ 2 ]
480- @nsstack . unshift ( curr_ns = Set . new )
481- attributes , closed = parse_attributes ( @prefixes , curr_ns )
480+ push_namespaces_restore
481+ attributes , closed = parse_attributes ( @prefixes )
482482 # Verify that all of the prefixes have been defined
483483 for prefix in @prefixes
484- unless @nsstack . find { | k | k . member ?( prefix ) }
484+ unless @namespaces . key ?( prefix )
485485 raise UndefinedNamespaceException . new ( prefix , @source , self )
486486 end
487487 end
488488
489489 if closed
490490 @closed = tag
491- @nsstack . shift
491+ pop_namespaces_restore
492492 else
493493 if @tags . empty? and @have_root
494494 raise ParseException . new ( "Malformed XML: Extra tag at the end of the document (got '<#{ tag } ')" , @source )
@@ -599,6 +599,31 @@ def unnormalize( string, entities=nil, filter=nil )
599599 end
600600
601601 private
602+ def add_namespace ( prefix , uri )
603+ @namespaces_restore_stack . last [ prefix ] = @namespaces [ prefix ]
604+ if uri . nil?
605+ @namespaces . delete ( prefix )
606+ else
607+ @namespaces [ prefix ] = uri
608+ end
609+ end
610+
611+ def push_namespaces_restore
612+ namespaces_restore = { }
613+ @namespaces_restore_stack . push ( namespaces_restore )
614+ namespaces_restore
615+ end
616+
617+ def pop_namespaces_restore
618+ namespaces_restore = @namespaces_restore_stack . pop
619+ namespaces_restore . each do |prefix , uri |
620+ if uri . nil?
621+ @namespaces . delete ( prefix )
622+ else
623+ @namespaces [ prefix ] = uri
624+ end
625+ end
626+ end
602627
603628 def record_entity_expansion ( delta = 1 )
604629 @entity_expansion_count += delta
@@ -727,7 +752,7 @@ def process_instruction
727752 [ :processing_instruction , name , content ]
728753 end
729754
730- def parse_attributes ( prefixes , curr_ns )
755+ def parse_attributes ( prefixes )
731756 attributes = { }
732757 closed = false
733758 while true
@@ -770,7 +795,7 @@ def parse_attributes(prefixes, curr_ns)
770795 "(http://www.w3.org/TR/REC-xml-names/#ns-decl)"
771796 raise REXML ::ParseException . new ( msg , @source , self )
772797 end
773- curr_ns << local_part
798+ add_namespace ( local_part , value )
774799 elsif prefix
775800 prefixes << prefix unless prefix == "xml"
776801 end
0 commit comments