mirror of
https://github.com/ruby/ruby.git
synced 2025-08-26 14:34:39 +02:00

r1352@bean: ser | 2007-07-29 11:33:07 -0400 Implements namespace validation in the baseparser. This means that, as per the XML namespace spec, unbound prefixes generate UndefinedNamespaceException. Also, as per the namespace spec, the 'xml' prefix must be bound to http://www.w3.org/XML/1998/namespace, and the 'xmlns' prefix must not be declared. in the XML. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@13595 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
96 lines
3.3 KiB
Ruby
96 lines
3.3 KiB
Ruby
require 'rexml/validation/validationexception'
|
|
|
|
module REXML
|
|
module Parsers
|
|
class TreeParser
|
|
def initialize( source, build_context = Document.new )
|
|
@build_context = build_context
|
|
@parser = Parsers::BaseParser.new( source )
|
|
end
|
|
|
|
def add_listener( listener )
|
|
@parser.add_listener( listener )
|
|
end
|
|
|
|
def parse
|
|
tag_stack = []
|
|
in_doctype = false
|
|
entities = nil
|
|
begin
|
|
while true
|
|
event = @parser.pull
|
|
#STDERR.puts "TREEPARSER GOT #{event.inspect}"
|
|
case event[0]
|
|
when :end_document
|
|
unless tag_stack.empty?
|
|
#raise ParseException.new("No close tag for #{tag_stack.inspect}")
|
|
raise ParseException.new("No close tag for #{@build_context.xpath}")
|
|
end
|
|
return
|
|
when :start_element
|
|
tag_stack.push(event[1])
|
|
el = @build_context = @build_context.add_element( event[1], event[2] )
|
|
when :end_element
|
|
tag_stack.pop
|
|
@build_context = @build_context.parent
|
|
when :text
|
|
if not in_doctype
|
|
if @build_context[-1].instance_of? Text
|
|
@build_context[-1] << event[1]
|
|
else
|
|
@build_context.add(
|
|
Text.new(event[1], @build_context.whitespace, nil, true)
|
|
) unless (
|
|
@build_context.ignore_whitespace_nodes and
|
|
event[1].strip.size==0
|
|
)
|
|
end
|
|
end
|
|
when :comment
|
|
c = Comment.new( event[1] )
|
|
@build_context.add( c )
|
|
when :cdata
|
|
c = CData.new( event[1] )
|
|
@build_context.add( c )
|
|
when :processing_instruction
|
|
@build_context.add( Instruction.new( event[1], event[2] ) )
|
|
when :end_doctype
|
|
in_doctype = false
|
|
entities.each { |k,v| entities[k] = @build_context.entities[k].value }
|
|
@build_context = @build_context.parent
|
|
when :start_doctype
|
|
doctype = DocType.new( event[1..-1], @build_context )
|
|
@build_context = doctype
|
|
entities = {}
|
|
in_doctype = true
|
|
when :attlistdecl
|
|
n = AttlistDecl.new( event[1..-1] )
|
|
@build_context.add( n )
|
|
when :externalentity
|
|
n = ExternalEntity.new( event[1] )
|
|
@build_context.add( n )
|
|
when :elementdecl
|
|
n = ElementDecl.new( event[1] )
|
|
@build_context.add(n)
|
|
when :entitydecl
|
|
entities[ event[1] ] = event[2] unless event[2] =~ /PUBLIC|SYSTEM/
|
|
@build_context.add(Entity.new(event))
|
|
when :notationdecl
|
|
n = NotationDecl.new( *event[1..-1] )
|
|
@build_context.add( n )
|
|
when :xmldecl
|
|
x = XMLDecl.new( event[1], event[2], event[3] )
|
|
@build_context.add( x )
|
|
end
|
|
end
|
|
rescue REXML::Validation::ValidationException
|
|
raise
|
|
rescue REXML::UndefinedNamespaceException
|
|
raise
|
|
rescue
|
|
raise ParseException.new( $!.message, @parser.source, @parser, $! )
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|