class Nokogiri::XML::SAX::Parser
def self.new(doc = XML::SAX::Document.new, encoding = 'UTF-8')
def self.new(doc = XML::SAX::Document.new, encoding = 'UTF-8') parser = allocate parser.document = doc parser.encoding = encoding parser.cstruct = LibXML::XmlSaxHandler.allocate parser.send(:setup_lambdas) parser.instance_variable_set(:@ctxt, nil) parser end
def __internal__cdataBlock(_, data, data_length)
def __internal__cdataBlock(_, data, data_length) @document.cdata_block data.slice(0, data_length) end
def __internal__characters(_, data, data_length)
def __internal__characters(_, data, data_length) @document.characters data.slice(0, data_length) end
def __internal__comment(_, data)
def __internal__comment(_, data) @document.comment data end
def __internal__endDocument(_)
def __internal__endDocument(_) @document.end_document end
def __internal__endElement(_, name)
def __internal__endElement(_, name) @document.end_element name end
def __internal__endElementNs(_, localname, prefix, uri)
def __internal__endElementNs(_, localname, prefix, uri) localname = localname.null? ? nil : localname.read_string prefix = prefix .null? ? nil : prefix .read_string uri = uri .null? ? nil : uri .read_string @document.end_element_namespace(localname, prefix, uri) end
def __internal__error(_, msg)
def __internal__error(_, msg) # TODO: vasprintf here @document.error(msg) end
def __internal__startDocument(_)
def __internal__startDocument(_) if @ctxt && @ctxt[:html] == 0 && @ctxt[:standalone] != -1 standalone = { 0 => 'no', 1 => 'yes', }[@ctxt[:standalone]] @document.xmldecl @ctxt[:version], @ctxt[:encoding], standalone end @document.start_document end
def __internal__startElement(_, name, attributes)
def __internal__startElement(_, name, attributes) attrs = attributes.null? ? [] : attributes.get_array_of_string(0) @document.start_element name, attrs end
def __internal__startElementNs(_, localname, prefix, uri, nb_namespaces, namespaces, nb_attributes, nb_defaulted, attributes)
def __internal__startElementNs(_, localname, prefix, uri, nb_namespaces, namespaces, nb_attributes, nb_defaulted, attributes) localname = localname.null? ? nil : localname.read_string prefix = prefix .null? ? nil : prefix .read_string uri = uri .null? ? nil : uri .read_string attr_list = [] ns_list = [] if ! attributes.null? # Each attribute is an array of [localname, prefix, URI, value, end] (0..(nb_attributes-1)*5).step(5) do |j| key = attributes.get_pointer(LibXML.pointer_offset(j)).read_string attr_prefix = attributes.get_pointer(LibXML.pointer_offset(j + 1)) attr_prefix = attr_prefix.null? ? nil : attr_prefix.read_string attr_uri = attributes.get_pointer(LibXML.pointer_offset(j + 2)) attr_uri = attr_uri.null? ? nil : attr_uri.read_string value_length = attributes.get_pointer(LibXML.pointer_offset(j+4)).address \ - attributes.get_pointer(LibXML.pointer_offset(j+3)).address value = attributes.get_pointer(LibXML.pointer_offset(j+3)).get_string(0, value_length) attr_list << Attribute.new(key, attr_prefix, attr_uri, value) end end if ! namespaces.null? (0..(nb_namespaces-1)*2).step(2) do |j| key = namespaces.get_pointer(LibXML.pointer_offset(j)) key = key.null? ? nil : key.read_string value = namespaces.get_pointer(LibXML.pointer_offset(j+1)) value = value.null? ? nil : value.read_string ns_list << [key, value] end end @document.start_element_namespace( localname, attr_list, prefix, uri, ns_list ) end
def __internal__warning(_, msg)
def __internal__warning(_, msg) # TODO: vasprintf here @document.warning(msg) end
def initialize doc = Nokogiri::XML::SAX::Document.new, encoding = 'UTF-8'
def initialize doc = Nokogiri::XML::SAX::Document.new, encoding = 'UTF-8' @encoding = encoding @document = doc @warned = false end
def parse thing, &block
Parse given +thing+ which may be a string containing xml, or an
##
def parse thing, &block if thing.respond_to?(:read) && thing.respond_to?(:close) parse_io(thing, &block) else parse_memory(thing, &block) end end
def parse_file filename
##
def parse_file filename raise ArgumentError unless filename raise Errno::ENOENT unless File.exists?(filename) raise Errno::EISDIR if File.directory?(filename) ctx = ParserContext.file filename yield ctx if block_given? ctx.parse_with self end
def parse_io io, encoding = 'ASCII'
##
def parse_io io, encoding = 'ASCII' @encoding = encoding ctx = ParserContext.io(io, ENCODINGS[encoding]) yield ctx if block_given? ctx.parse_with self end
def parse_memory data
def parse_memory data ctx = ParserContext.memory data yield ctx if block_given? ctx.parse_with self end
def setup_lambdas
def setup_lambdas @closures = {} # we need to keep references to the closures to avoid GC [ :startDocument, :endDocument, :startElement, :endElement, :characters, :comment, :warning, :error, :cdataBlock, :startElementNs, :endElementNs ].each do |sym| @closures[sym] = lambda { |*args| send("__internal__#{sym}", *args) } # "i'm your private dancer", etc. end @closures.each { |k,v| cstruct[k] = v } cstruct[:initialized] = Nokogiri::LibXML::XmlSaxHandler::XML_SAX2_MAGIC end