class Nokogiri::XML::Reader
def self.from_io(io, url=nil, encoding=nil, options=0)
def self.from_io(io, url=nil, encoding=nil, options=0) raise(ArgumentError, "io cannot be nil") if io.nil? cb = IoCallbacks.reader(io) # we will keep a reference to prevent it from being GC'd reader_ptr = LibXML.xmlReaderForIO(cb, nil, nil, url, encoding, options) raise "couldn't create a parser" if reader_ptr.null? reader = allocate reader.cstruct = LibXML::XmlTextReader.new(reader_ptr) reader.send(:initialize, io, url, encoding) reader.reader_callback = cb reader end
def self.from_memory(buffer, url=nil, encoding=nil, options=0)
def self.from_memory(buffer, url=nil, encoding=nil, options=0) raise(ArgumentError, "string cannot be nil") if buffer.nil? memory = FFI::MemoryPointer.new(buffer.length) # we need to manage native memory lifecycle memory.put_bytes(0, buffer) reader_ptr = LibXML.xmlReaderForMemory(memory, memory.total, url, encoding, options) raise(RuntimeError, "couldn't create a reader") if reader_ptr.null? reader = allocate reader.cstruct = LibXML::XmlTextReader.new(reader_ptr) reader.send(:initialize, memory, url, encoding) reader end
def attr_nodes
def attr_nodes return {} unless attributes? ptr = LibXML.xmlTextReaderExpand(cstruct) return nil if ptr.null? node_struct = LibXML::XmlNode.new(ptr) Node.node_properties node_struct end
def attribute(name)
def attribute(name) return nil if name.nil? attr_ptr = LibXML.xmlTextReaderGetAttribute(cstruct, name.to_s) if attr_ptr.null? # this section is an attempt to workaround older versions of libxml that # don't handle namespaces properly in all attribute-and-friends functions prefix_ptr = FFI::Buffer.new :pointer localname = LibXML.xmlSplitQName2(name, prefix_ptr) prefix = prefix_ptr.get_pointer(0) if ! localname.null? attr_ptr = LibXML.xmlTextReaderLookupNamespace(cstruct, localname.read_string) LibXML.xmlFree(localname) else if prefix.null? || prefix.read_string.length == 0 attr_ptr = LibXML.xmlTextReaderLookupNamespace(cstruct, nil) else attr_ptr = LibXML.xmlTextReaderLookupNamespace(cstruct, prefix.read_string) end end LibXML.xmlFree(prefix) end return nil if attr_ptr.null? attr = attr_ptr.read_string LibXML.xmlFree(attr_ptr) attr end
def attribute_at(index)
def attribute_at(index) return nil if index.nil? index = index.to_i attr_ptr = LibXML.xmlTextReaderGetAttributeNo(cstruct, index) return nil if attr_ptr.null? attr = attr_ptr.read_string LibXML.xmlFree attr_ptr attr end
def attribute_count
def attribute_count count = LibXML.xmlTextReaderAttributeCount(cstruct) count == -1 ? nil : count end
def attribute_nodes
##
def attribute_nodes nodes = attr_nodes nodes.each { |v| v.instance_variable_set(:@_r, self) } nodes end
def attributes
##
def attributes Hash[*(attribute_nodes.map { |node| [node.name, node.to_s] }.flatten)].merge(namespaces || {}) end
def attributes?
def attributes? # this implementation of xmlTextReaderHasAttributes explicitly includes # namespaces and properties, because some earlier versions ignore # namespaces. node_ptr = LibXML.xmlTextReaderCurrentNode(cstruct) return false if node_ptr.null? node = LibXML::XmlNode.new node_ptr node[:type] == Node::ELEMENT_NODE && (!node[:properties].null? || !node[:nsDef].null?) end
def default?
def default? LibXML.xmlTextReaderIsDefault(cstruct) == 1 end
def depth
def depth val = LibXML.xmlTextReaderDepth(cstruct) val == -1 ? nil : val end
def each(&block)
##
def each(&block) while node = self.read block.call(node) end end
def initialize source, url = nil, encoding = nil # :nodoc:
def initialize source, url = nil, encoding = nil # :nodoc: @source = source @errors = [] @encoding = encoding end
def inner_xml
def inner_xml string_ptr = LibXML.xmlTextReaderReadInnerXml(cstruct) return nil if string_ptr.null? string = string_ptr.read_string LibXML.xmlFree(string_ptr) string end
def lang
def lang val = LibXML.xmlTextReaderConstXmlLang(cstruct) val.null? ? nil : val.read_string end
def local_name
def local_name val = LibXML.xmlTextReaderConstLocalName(cstruct) val.null? ? nil : val.read_string end
def name
def name val = LibXML.xmlTextReaderConstName(cstruct) val.null? ? nil : val.read_string end
def namespace_uri
def namespace_uri val = LibXML.xmlTextReaderConstNamespaceUri(cstruct) val.null? ? nil : val.read_string end
def namespaces
def namespaces return {} unless attributes? ptr = LibXML.xmlTextReaderExpand(cstruct) return nil if ptr.null? Reader.node_namespaces(ptr) end
def node_namespaces(ptr)
def node_namespaces(ptr) cstruct = LibXML::XmlNode.new(ptr) ahash = {} return ahash unless cstruct[:type] == Node::ELEMENT_NODE ns = cstruct[:nsDef] while ! ns.null? ns_cstruct = LibXML::XmlNs.new(ns) prefix = ns_cstruct[:prefix] key = if prefix.nil? || prefix.empty? "xmlns" else "xmlns:#{prefix}" end ahash[key] = ns_cstruct[:href] # TODO: encoding? ns = ns_cstruct[:next] # TODO: encoding? end ahash end
def node_type
def node_type LibXML.xmlTextReaderNodeType(cstruct) end
def outer_xml
def outer_xml string_ptr = LibXML.xmlTextReaderReadOuterXml(cstruct) return nil if string_ptr.null? string = string_ptr.read_string LibXML.xmlFree(string_ptr) string end
def prefix
def prefix val = LibXML.xmlTextReaderConstPrefix(cstruct) val.null? ? nil : val.read_string end
def read
def read error_list = self.errors LibXML.xmlSetStructuredErrorFunc(nil, SyntaxError.error_array_pusher(error_list)) ret = LibXML.xmlTextReaderRead(cstruct) LibXML.xmlSetStructuredErrorFunc(nil, nil) return self if ret == 1 return nil if ret == 0 error = LibXML.xmlGetLastError() if error raise SyntaxError.wrap(error) else raise RuntimeError, "Error pulling: #{ret}" end nil end
def state
def state LibXML.xmlTextReaderReadState(cstruct) end
def value
def value val = LibXML.xmlTextReaderConstValue(cstruct) val.null? ? nil : val.read_string end
def value?
def value? LibXML.xmlTextReaderHasValue(cstruct) == 1 end
def xml_version
def xml_version val = LibXML.xmlTextReaderConstXmlVersion(cstruct) val.null? ? nil : val.read_string end