| Module | RSS::ListenerMixin |
| In: |
lib/rss/parser.rb
lib/rss/0.9.rb lib/rss/1.0.rb |
| CONTENT_PATTERN | = | /\s*([^=]+)=(["'])([^\2]+?)\2/ |
| NAMESPLIT | = | /^(?:([\w:][-\w\d.]*):)?([\w:][-\w\d.]*)/ |
| do_validate | [RW] | |
| ignore_unknown_element | [RW] | |
| rss | [R] |
# File lib/rss/parser.rb, line 271
271: def initialize
272: @rss = nil
273: @ignore_unknown_element = true
274: @do_validate = true
275: @ns_stack = [{}]
276: @tag_stack = [[]]
277: @text_stack = ['']
278: @proc_stack = []
279: @last_element = nil
280: @version = @encoding = @standalone = nil
281: @xml_stylesheets = []
282: end
# File lib/rss/parser.rb, line 289
289: def instruction(name, content)
290: if name == "xml-stylesheet"
291: params = parse_pi_content(content)
292: if params.has_key?("href")
293: @xml_stylesheets << XMLStyleSheet.new(*params)
294: end
295: end
296: end
# File lib/rss/parser.rb, line 322
322: def tag_end(name)
323: if DEBUG
324: p "end tag #{name}"
325: p @tag_stack
326: end
327: text = @text_stack.pop
328: tags = @tag_stack.pop
329: pr = @proc_stack.pop
330: pr.call(text, tags) unless pr.nil?
331: @ns_stack.pop
332: end
# File lib/rss/parser.rb, line 298
298: def tag_start(name, attributes)
299: @text_stack.push('')
300:
301: ns = @ns_stack.last.dup
302: attrs = {}
303: attributes.each do |n, v|
304: if /\Axmlns(?:\z|:)/ =~ n
305: ns[$POSTMATCH] = v
306: else
307: attrs[n] = v
308: end
309: end
310: @ns_stack.push(ns)
311:
312: prefix, local = split_name(name)
313: @tag_stack.last.push([_ns(ns, prefix), local])
314: @tag_stack.push([])
315: if respond_to?("start_#{local}", true)
316: __send__("start_#{local}", local, prefix, attrs, ns.dup)
317: else
318: start_else_element(local, prefix, attrs, ns.dup)
319: end
320: end
set instance vars for version, encoding, standalone
# File lib/rss/parser.rb, line 285
285: def xmldecl(version, encoding, standalone)
286: @version, @encoding, @standalone = version, encoding, standalone
287: end
# File lib/rss/parser.rb, line 380
380: def check_ns(tag_name, prefix, ns, require_uri)
381: if @do_validate
382: if _ns(ns, prefix) == require_uri
383: #ns.delete(prefix)
384: else
385: raise NSError.new(tag_name, prefix, require_uri)
386: end
387: end
388: end
Extract the first name="value" pair from content. Works with single quotes according to the constant CONTENT_PATTERN. Return a Hash.
# File lib/rss/parser.rb, line 347
347: def parse_pi_content(content)
348: params = {}
349: content.scan(CONTENT_PATTERN) do |name, quote, value|
350: params[name] = value
351: end
352: params
353: end
# File lib/rss/parser.rb, line 375
375: def split_name(name)
376: name =~ NAMESPLIT
377: [$1 || '', $2]
378: end
# File lib/rss/1.0.rb, line 438
438: def start_RDF(tag_name, prefix, attrs, ns)
439: check_ns(tag_name, prefix, ns, RDF::URI)
440:
441: @rss = RDF.new(@version, @encoding, @standalone)
442: @rss.do_validate = @do_validate
443: @rss.xml_stylesheets = @xml_stylesheets
444: @last_element = @rss
445: @proc_stack.push Proc.new { |text, tags|
446: @rss.validate_for_stream(tags, @ignore_unknown_element) if @do_validate
447: }
448: end
# File lib/rss/parser.rb, line 355
355: def start_else_element(local, prefix, attrs, ns)
356: class_name = self.class.class_name(_ns(ns, prefix), local)
357: current_class = @last_element.class
358: if current_class.constants.include?(class_name)
359: next_class = current_class.const_get(class_name)
360: start_have_something_element(local, prefix, attrs, ns, next_class)
361: else
362: if !@do_validate or @ignore_unknown_element
363: @proc_stack.push(nil)
364: else
365: parent = "ROOT ELEMENT???"
366: if current_class.tag_name
367: parent = current_class.tag_name
368: end
369: raise NotExpectedTagError.new(local, _ns(ns, prefix), parent)
370: end
371: end
372: end
# File lib/rss/parser.rb, line 390
390: def start_get_text_element(tag_name, prefix, ns, required_uri)
391: @proc_stack.push Proc.new {|text, tags|
392: setter = self.class.setter(required_uri, tag_name)
393: if @last_element.respond_to?(setter)
394: @last_element.__send__(setter, text.to_s)
395: else
396: if @do_validate and !@ignore_unknown_element
397: raise NotExpectedTagError.new(tag_name, _ns(ns, prefix),
398: @last_element.tag_name)
399: end
400: end
401: }
402: end
# File lib/rss/parser.rb, line 404
404: def start_have_something_element(tag_name, prefix, attrs, ns, klass)
405:
406: check_ns(tag_name, prefix, ns, klass.required_uri)
407:
408: attributes = {}
409: klass.get_attributes.each do |a_name, a_uri, required, element_name|
410:
411: if a_uri.is_a?(String) or !a_uri.respond_to?(:include?)
412: a_uri = [a_uri]
413: end
414: unless a_uri == [""]
415: for prefix, uri in ns
416: if a_uri.include?(uri)
417: val = attrs["#{prefix}:#{a_name}"]
418: break if val
419: end
420: end
421: end
422: if val.nil? and a_uri.include?("")
423: val = attrs[a_name]
424: end
425:
426: if @do_validate and required and val.nil?
427: unless a_uri.include?("")
428: for prefix, uri in ns
429: if a_uri.include?(uri)
430: a_name = "#{prefix}:#{a_name}"
431: end
432: end
433: end
434: raise MissingAttributeError.new(tag_name, a_name)
435: end
436:
437: attributes[a_name] = val
438: end
439:
440: previous = @last_element
441: next_element = klass.new(@do_validate, attributes)
442: previous.instance_eval {set_next_element(tag_name, next_element)}
443: @last_element = next_element
444: @proc_stack.push Proc.new { |text, tags|
445: p(@last_element.class) if DEBUG
446: @last_element.content = text if klass.have_content?
447: if @do_validate
448: @last_element.validate_for_stream(tags, @ignore_unknown_element)
449: end
450: @last_element = previous
451: }
452: end
# File lib/rss/0.9.rb, line 408
408: def start_rss(tag_name, prefix, attrs, ns)
409: check_ns(tag_name, prefix, ns, "")
410:
411: @rss = Rss.new(attrs['version'], @version, @encoding, @standalone)
412: @rss.do_validate = @do_validate
413: @rss.xml_stylesheets = @xml_stylesheets
414: @last_element = @rss
415: @proc_stack.push Proc.new { |text, tags|
416: @rss.validate_for_stream(tags, @ignore_unknown_element) if @do_validate
417: }
418: end