class Nokogiri::XML::SAX::PushParser - nokogiri-1.18.10 Documentation

# class Nokogiri::XML::SAX::PushParser

`PushParser` can parse a document that is fed to it manually. It must be given a `SAX::Document` object which will be called with `SAX` events as the document is being parsed.

Calling `PushParser#<<` writes `XML` to the parser, calling any `SAX` callbacks it can.

`PushParser#finish` tells the parser that the document is finished and calls the end_document `SAX` method.

Example:

    parser = PushParser.new(Class.new(XML::SAX::Document) {
      def start_document
        puts "start document called"
      end
    }.new)
    parser << "<div>hello<"
    parser << "/div>"
    parser.finish

### Attributes

document[RW]

The `Nokogiri::XML::SAX::Document` on which the `PushParser` will be operating

### Public Class Methods

new(doc = XML::SAX::Document.new, file_name = nil, encoding = "UTF-8") click to toggle source

Create a new `PushParser` with `doc` as the `SAX` `Document`, providing an optional `file_name` and `encoding`

    # File lib/nokogiri/xml/sax/push_parser.rb, line 35
    def initialize(doc = XML::SAX::Document.new, file_name = nil, encoding = "UTF-8")
      @document = doc
      @encoding = encoding
      @sax_parser = XML::SAX::Parser.new(doc)

      ## Create our push parser context
      initialize_native(@sax_parser, file_name)
    end

### Public Instance Methods

<<(chunk, last_chunk = false)
Alias for: write
finish() click to toggle source

Finish the parsing. This method is only necessary for `Nokogiri::XML::SAX::Document#end_document` to be called.

⚠ Note that empty documents are treated as an error when using the libxml2-based implementation (CRuby), but are fine when using the Xerces-based implementation (JRuby).

    # File lib/nokogiri/xml/sax/push_parser.rb, line 58
    def finish
      write("", true)
    end

options() click to toggle source

    static VALUE
    noko_xml_sax_push_parser__options_get(VALUE self)
    {
      xmlParserCtxtPtr ctx;

      ctx = noko_xml_sax_push_parser_unwrap(self);

      return INT2NUM(xmlCtxtGetOptions(ctx));
    }

options=(p1) click to toggle source

    static VALUE
    noko_xml_sax_push_parser__options_set(VALUE self, VALUE options)
    {
      int error;
      xmlParserCtxtPtr ctx;

      ctx = noko_xml_sax_push_parser_unwrap(self);

      error = xmlCtxtSetOptions(ctx, (int)NUM2INT(options));
      if (error) {
        rb_raise(rb_eRuntimeError, "Cannot set XML parser context options (%x)", error);
      }

      return Qnil;
    }

replace_entities click to toggle source

See Entity Handling at `Document` for an explanation of the behavior controlled by this flag.

Returns

  (Boolean) Value of the parse option. (Default `false`)

This option is perhaps misnamed by the libxml2 author, since it controls resolution and not replacement.

    static VALUE
    noko_xml_sax_push_parser__replace_entities_get(VALUE self)
    {
      xmlParserCtxtPtr ctxt = noko_xml_sax_push_parser_unwrap(self);

      if (xmlCtxtGetOptions(ctxt) & XML_PARSE_NOENT) {
        return Qtrue;
      } else {
        return Qfalse;
      }
    }

replace_entities=(value) click to toggle source

See Entity Handling at `Document` for an explanation of the behavior controlled by this flag.

Parameters

- `value` (Boolean) Whether external parsed entities will be resolved.

⚠ It is UNSAFE to set this option to `true` when parsing untrusted documents. The option defaults to `false` for this reason.

This option is perhaps misnamed by the libxml2 author, since it controls resolution and not replacement.

    static VALUE
    noko_xml_sax_push_parser__replace_entities_set(VALUE self, VALUE value)
    {
      int error;
      xmlParserCtxtPtr ctxt = noko_xml_sax_push_parser_unwrap(self);

      if (RB_TEST(value)) {
        error = xmlCtxtSetOptions(ctxt, xmlCtxtGetOptions(ctxt) | XML_PARSE_NOENT);
      } else {
        error = xmlCtxtSetOptions(ctxt, xmlCtxtGetOptions(ctxt) & ~XML_PARSE_NOENT);
      }

      if (error) {
        rb_raise(rb_eRuntimeError, "failed to set parser context options (%x)", error);
      }

      return value;
    }

write(chunk, last_chunk = false) click to toggle source

Write a `chunk` of `XML` to the `PushParser`. Any callback methods that can be called will be called immediately.

    # File lib/nokogiri/xml/sax/push_parser.rb, line 47
    def write(chunk, last_chunk = false)
      native_write(chunk, last_chunk)
    end

Also aliased as: <<

### Private Instance Methods

initialize_native(xml_sax, filename) click to toggle source

Initialize the push parser with `xml_sax` using `filename`

    static VALUE
    noko_xml_sax_push_parser__initialize_native(VALUE self, VALUE _xml_sax, VALUE _filename)
    {
      xmlSAXHandlerPtr sax;
      const char *filename = NULL;
      xmlParserCtxtPtr ctx;

      sax = noko_xml_sax_parser_unwrap(_xml_sax);

      if (_filename != Qnil) { filename = StringValueCStr(_filename); }

      ctx = xmlCreatePushParserCtxt(
              sax,
              NULL,
              NULL,
              0,
              filename
            );
      if (ctx == NULL) {
        rb_raise(rb_eRuntimeError, "Could not create a parser context");
      }

      ctx->userData = ctx;
      ctx->_private = (void *)_xml_sax;

      DATA_PTR(self) = ctx;
      return self;
    }

native_write(p1, p2) click to toggle source

Write `chunk` to `PushParser`. `last_chunk` triggers the end_document handle

    static VALUE
    noko_xml_sax_push_parser__native_write(VALUE self, VALUE _chunk, VALUE _last_chunk)
    {
      xmlParserCtxtPtr ctx;
      const char *chunk  = NULL;
      int size            = 0;

      ctx = noko_xml_sax_push_parser_unwrap(self);

      if (Qnil != _chunk) {
        chunk = StringValuePtr(_chunk);
        size = (int)RSTRING_LEN(_chunk);
      }

      xmlSetStructuredErrorFunc(NULL, NULL);

      if (xmlParseChunk(ctx, chunk, size, Qtrue == _last_chunk ? 1 : 0)) {
        if (!(xmlCtxtGetOptions(ctx) & XML_PARSE_RECOVER)) {
          xmlErrorConstPtr e = xmlCtxtGetLastError(ctx);
          noko__error_raise(NULL, e);
        }
      }

      return self;
    }