Ensure SAX after_element receives meaningful args
This changes the behaviour of after_element when parsing documents using the SAX parsing API. Previously it would always receive a nil argument, which is kinda pointless. This commit changes that by making sure it receives a namespace name (if any) and the element name. This fixes #54.
This commit is contained in:
parent
8c8ecce447
commit
57adabc068
|
|
@ -182,6 +182,8 @@ The documentation is best viewed [on the documentation website][doc-website].
|
||||||
* {file:CONTRIBUTING Contributing}
|
* {file:CONTRIBUTING Contributing}
|
||||||
* {file:changelog Changelog}
|
* {file:changelog Changelog}
|
||||||
* {file:migrating\_from\_nokogiri Migrating From Nokogiri}
|
* {file:migrating\_from\_nokogiri Migrating From Nokogiri}
|
||||||
|
* {Oga::XML::Parser XML Parser}
|
||||||
|
* {Oga::XML::SaxParser XML SAX Parser}
|
||||||
|
|
||||||
## Native Extension Setup
|
## Native Extension Setup
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -37,6 +37,26 @@ module Oga
|
||||||
# For information on the callback arguments see the documentation of the
|
# For information on the callback arguments see the documentation of the
|
||||||
# corresponding methods in {Oga::XML::Parser}.
|
# corresponding methods in {Oga::XML::Parser}.
|
||||||
#
|
#
|
||||||
|
# ## Element Callbacks
|
||||||
|
#
|
||||||
|
# The SAX parser changes the behaviour of both `on_element` and
|
||||||
|
# `after_element`. The latter in the regular parser only takes a
|
||||||
|
# {Oga::XML::Element} instance. In the SAX parser it will instead take a
|
||||||
|
# namespace name and the element name. This eases the process of figuring
|
||||||
|
# out what element a callback is associated with.
|
||||||
|
#
|
||||||
|
# An example:
|
||||||
|
#
|
||||||
|
# class SaxHandler
|
||||||
|
# def on_element(namespace, name, attrs = {})
|
||||||
|
# # ...
|
||||||
|
# end
|
||||||
|
#
|
||||||
|
# def after_element(namespace, name)
|
||||||
|
# puts name # => "foo", "bar", etc
|
||||||
|
# end
|
||||||
|
# end
|
||||||
|
#
|
||||||
class SaxParser < Parser
|
class SaxParser < Parser
|
||||||
##
|
##
|
||||||
# @param [Object] handler The SAX handler to delegate callbacks to.
|
# @param [Object] handler The SAX handler to delegate callbacks to.
|
||||||
|
|
@ -52,12 +72,46 @@ module Oga
|
||||||
instance_methods.grep(/^(on_|after_)/).each do |method|
|
instance_methods.grep(/^(on_|after_)/).each do |method|
|
||||||
eval <<-EOF, nil, __FILE__, __LINE__ + 1
|
eval <<-EOF, nil, __FILE__, __LINE__ + 1
|
||||||
def #{method}(*args)
|
def #{method}(*args)
|
||||||
@handler.#{method}(*args) if @handler.respond_to?(:#{method})
|
run_callback(:#{method}, *args)
|
||||||
|
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
EOF
|
EOF
|
||||||
end
|
end
|
||||||
|
|
||||||
|
##
|
||||||
|
# Manually overwrite `on_element` so we can ensure that `after_element`
|
||||||
|
# always receives the namespace and name.
|
||||||
|
#
|
||||||
|
# @see [Oga::XML::Parser#on_element]
|
||||||
|
# @return [Array]
|
||||||
|
#
|
||||||
|
def on_element(namespace, name, attrs = {})
|
||||||
|
run_callback(:on_element, namespace, name, attrs)
|
||||||
|
|
||||||
|
return namespace, name
|
||||||
|
end
|
||||||
|
|
||||||
|
##
|
||||||
|
# Manually overwrite `after_element` so it can take a namespace and name.
|
||||||
|
# This differs a bit from the regular `after_element` which only takes an
|
||||||
|
# {Oga::XML::Element} instance.
|
||||||
|
#
|
||||||
|
# @param [Array] namespace_with_name
|
||||||
|
#
|
||||||
|
def after_element(namespace_with_name)
|
||||||
|
run_callback(:after_element, *namespace_with_name)
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
##
|
||||||
|
# @param [Symbol] method
|
||||||
|
# @param [Array] args
|
||||||
|
#
|
||||||
|
def run_callback(method, *args)
|
||||||
|
@handler.send(method, *args) if @handler.respond_to?(method)
|
||||||
|
end
|
||||||
end # SaxParser
|
end # SaxParser
|
||||||
end # XML
|
end # XML
|
||||||
end # Oga
|
end # Oga
|
||||||
|
|
|
||||||
|
|
@ -3,11 +3,16 @@ require 'spec_helper'
|
||||||
describe Oga::XML::SaxParser do
|
describe Oga::XML::SaxParser do
|
||||||
before do
|
before do
|
||||||
@handler = Class.new do
|
@handler = Class.new do
|
||||||
attr_reader :name
|
attr_reader :name, :after_namespace, :after_name
|
||||||
|
|
||||||
def on_element(namespace, name, attrs = {})
|
def on_element(namespace, name, attrs = {})
|
||||||
@name = name
|
@name = name
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def after_element(namespace, name)
|
||||||
|
@after_namespace = namespace
|
||||||
|
@after_name = name
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
@ -26,6 +31,16 @@ describe Oga::XML::SaxParser do
|
||||||
handler.name.should == 'foo'
|
handler.name.should == 'foo'
|
||||||
end
|
end
|
||||||
|
|
||||||
|
example 'always pass element names to after_element' do
|
||||||
|
handler = @handler.new
|
||||||
|
parser = described_class.new(handler, '<namespace:foo />')
|
||||||
|
|
||||||
|
parser.parse
|
||||||
|
|
||||||
|
handler.after_name.should == 'foo'
|
||||||
|
handler.after_namespace.should == 'namespace'
|
||||||
|
end
|
||||||
|
|
||||||
example 'ignore callbacks that are not defined in the handler' do
|
example 'ignore callbacks that are not defined in the handler' do
|
||||||
parser = described_class.new(@handler.new, '<!--foo-->')
|
parser = described_class.new(@handler.new, '<!--foo-->')
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue