require 'xmlscan' module XML class ParserError < Exception; end class Parser < XMLScanner DEFAULT = 0 START_ELEM = 1 END_ELEM = 2 CDATA = 3 PI = 4 UNPARSED_ENTITY_DECL = 5 NOTATION_DECL = 6 EXTERNAL_ENTITY_REF = 7 COMMENT = 8 START_CDATA = 9 END_CDATA = 10 START_NAMESPACE_DECL = 11 END_NAMESPACE_DECL = 12 UNKNOWN_ENCODING = 13 def initialize(*args) @inDocument = false @exception = nil @block = nil @line = nil super() end def parse(str, *rest, &block) @block = block super(str) end def on_error(path, lineno, msg) @line = lineno raise ParserError.new(msg) end def on_comment(strs) if @block @block.call(COMMENT, nil, strs.join) if respond_to?(:comment) else comment(strs.join) if respond_to?(:comment) end end def on_pi(target, pi) if @block @block.call(PI, target, pi) else processingInstruction(target, pi) if respond_to?(:processingInstruction) end end def on_chardata(str) return unless @inDocument if @block @block.call(CDATA, nil,str) else character(str) if respond_to?(:character) end end def on_etag(name) @inDocument = false if @inDocument == name if @block @block.call(END_ELEM, name, nil) else endElement(name) if respond_to?(:endElement) end end def on_stag(name, attr) @inDocument = name unless @inDocument if @block @block.call(START_ELEM, name, attr) else startElement(name, attr) if respond_to?(:startElement) end end def on_emptyelem(name, attr) if @block @block.call(START_ELEM, name, attr) @block.call(END_ELEM, name, nil) else startElement(name, attr) if respond_to?(:startElement) endElement(name) if respond_to?(:endElement) end end def done; end def defaultCurrent; end def line return @line if @line 0 end def column 0 end def byteIndex 0 end def setBase(baseURL); end end end