class Nokogiri::XML::Schema - nokogiri-1.15.2 Documentation

# class Nokogiri::XML::Schema

`Nokogiri::XML::Schema` is used for validating `XML` against a schema (usually from an xsd file).

## Synopsis¶ ↑

Validate an `XML` document against a `Schema`. Loop over the errors that are returned and print them out:

    xsd = Nokogiri::XML::Schema(File.read(PO_SCHEMA_FILE))
    doc = Nokogiri::XML(File.read(PO_XML_FILE))

    xsd.validate(doc).each do |error|
      puts error.message
    end

The list of errors are `Nokogiri::XML::SyntaxError` objects.

NOTE: As of v1.11.0, `Schema` treats inputs as UNTRUSTED by default, and so external entities are not resolved from the network (‘http://` or `ftp://`). Previously, parsing treated documents as “trusted” by default which was counter to Nokogiri’s “untrusted by default” security policy. If a document is trusted, then the caller may turn off the NONET option via the `ParseOptions` to re-enable external entity resolution over a network connection.

### Attributes

errors[RW]

Errors while parsing the schema file

parse_options[RW]

The `Nokogiri::XML::ParseOptions` used to parse the schema

### Public Class Methods

from_document(document) → Nokogiri::XML::Schema click to toggle source

Create a new schema parsed from the `document`.

Parameters

- `document`: `Nokogiri::XML::Document` to be parsed

Returns

  `Nokogiri::XML::Schema`

    static VALUE
    from_document(int argc, VALUE *argv, VALUE klass)
    {
      VALUE rb_document;
      VALUE rb_parse_options;
      VALUE rb_schema;
      xmlDocPtr c_document;
      xmlSchemaParserCtxtPtr c_parser_context;
      int defensive_copy_p = 0;

      rb_scan_args(argc, argv, "11", &rb_document, &rb_parse_options);

      if (rb_obj_is_kind_of(rb_document, cNokogiriXmlDocument)) {
        c_document = noko_xml_document_unwrap(rb_document);
      } else {
        xmlNodePtr deprecated_node_type_arg;
        // TODO: deprecate allowing Node
        NOKO_WARN_DEPRECATION("Passing a Node as the first parameter to Schema.from_document is deprecated. Please pass a Document instead. This will become an error in a future release of Nokogiri.");
        Noko_Node_Get_Struct(rb_document, xmlNode, deprecated_node_type_arg);
        c_document = deprecated_node_type_arg->doc;
      }

      if (noko_xml_document_has_wrapped_blank_nodes_p(c_document)) {
        // see https://github.com/sparklemotion/nokogiri/pull/2001
        c_document = xmlCopyDoc(c_document, 1);
        defensive_copy_p = 1;
      }

      c_parser_context = xmlSchemaNewDocParserCtxt(c_document);
      rb_schema = xml_schema_parse_schema(klass, c_parser_context, rb_parse_options);

      if (defensive_copy_p) {
        xmlFreeDoc(c_document);
        c_document = NULL;
      }

      return rb_schema;
    }

new(string_or_io, options = ParseOptions::DEFAULT_SCHEMA) click to toggle source

Create a new `Nokogiri::XML::Schema` object using a `string_or_io` object.

    # File lib/nokogiri/xml/schema.rb, line 46
    def self.new(string_or_io, options = ParseOptions::DEFAULT_SCHEMA)
      from_document(Nokogiri::XML(string_or_io), options)
    end

read_memory(string) → Nokogiri::XML::Schema click to toggle source

Create a new schema parsed from the contents of `string`

Parameters

- `string`: String containing `XML` to be parsed as a schema

Returns

  `Nokogiri::XML::Schema`

    static VALUE
    read_memory(int argc, VALUE *argv, VALUE klass)
    {
      VALUE rb_content;
      VALUE rb_parse_options;
      xmlSchemaParserCtxtPtr c_parser_context;

      rb_scan_args(argc, argv, "11", &rb_content, &rb_parse_options);

      c_parser_context = xmlSchemaNewMemParserCtxt(
                           (const char *)StringValuePtr(rb_content),
                           (int)RSTRING_LEN(rb_content)
                         );

      return xml_schema_parse_schema(klass, c_parser_context, rb_parse_options);
    }

### Public Instance Methods

valid?(thing) click to toggle source

Returns true if `thing` is a valid `Nokogiri::XML::Document` or file.

    # File lib/nokogiri/xml/schema.rb, line 68
    def valid?(thing)
      validate(thing).empty?
    end

validate(thing) click to toggle source

Validate `thing` against this schema. `thing` can be a `Nokogiri::XML::Document` object, or a filename. An Array of `Nokogiri::XML::SyntaxError` objects found while validating the `thing` is returned.

    # File lib/nokogiri/xml/schema.rb, line 55
    def validate(thing)
      if thing.is_a?(Nokogiri::XML::Document)
        validate_document(thing)
      elsif File.file?(thing)
        validate_file(thing)
      else
        raise ArgumentError, "Must provide Nokogiri::Xml::Document or the name of an existing file"
      end
    end

### Private Instance Methods

validate_document(document) click to toggle source

Validate a `Nokogiri::XML::Document` against this `Schema`.

    static VALUE
    validate_document(VALUE self, VALUE document)
    {
      xmlDocPtr doc;
      xmlSchemaPtr schema;
      xmlSchemaValidCtxtPtr valid_ctxt;
      VALUE errors;

      TypedData_Get_Struct(self, xmlSchema, &xml_schema_type, schema);
      doc = noko_xml_document_unwrap(document);

      errors = rb_ary_new();

      valid_ctxt = xmlSchemaNewValidCtxt(schema);

      if (NULL == valid_ctxt) {
        /* we have a problem */
        rb_raise(rb_eRuntimeError, "Could not create a validation context");
      }

    #ifdef HAVE_XMLSCHEMASETVALIDSTRUCTUREDERRORS
      xmlSchemaSetValidStructuredErrors(
        valid_ctxt,
        Nokogiri_error_array_pusher,
        (void *)errors
      );
    #endif

      xmlSchemaValidateDoc(valid_ctxt, doc);

      xmlSchemaFreeValidCtxt(valid_ctxt);

      return errors;
    }

validate_file(filename) click to toggle source

Validate a file against this `Schema`.

    static VALUE
    validate_file(VALUE self, VALUE rb_filename)
    {
      xmlSchemaPtr schema;
      xmlSchemaValidCtxtPtr valid_ctxt;
      const char *filename ;
      VALUE errors;

      TypedData_Get_Struct(self, xmlSchema, &xml_schema_type, schema);
      filename = (const char *)StringValueCStr(rb_filename) ;

      errors = rb_ary_new();

      valid_ctxt = xmlSchemaNewValidCtxt(schema);

      if (NULL == valid_ctxt) {
        /* we have a problem */
        rb_raise(rb_eRuntimeError, "Could not create a validation context");
      }

    #ifdef HAVE_XMLSCHEMASETVALIDSTRUCTUREDERRORS
      xmlSchemaSetValidStructuredErrors(
        valid_ctxt,
        Nokogiri_error_array_pusher,
        (void *)errors
      );
    #endif

      xmlSchemaValidateFile(valid_ctxt, filename, 0);

      xmlSchemaFreeValidCtxt(valid_ctxt);

      return errors;
    }