#include "ruby_libxml.h" #define LIBXML_OUTPUT_ENABLED #define DUMP_CONTENT_MODEL #include "ruby_xml_schema.h" #include "ruby_xml_schema_type.h" #include "ruby_xml_schema_element.h" #include "ruby_xml_schema_attribute.h" #include "ruby_xml_schema_facet.h" /* * Document-class: LibXML::XML::Schema * * The XML::Schema class is used to prepare XML Schemas for validation of xml * documents. * * Schemas can be created from XML documents, strinings or URIs using the * corresponding methods (new for URIs). * * Once a schema is prepared, an XML document can be validated by the * XML::Document#validate_schema method providing the XML::Schema object * as parameter. The method return true if the document validates, false * otherwise. * * Basic usage: * * # parse schema as xml document * schema_document = XML::Document.file('schema.rng') * * # prepare schema for validation * schema = XML::Schema.document(schema_document) * * # parse xml document to be validated * instance = XML::Document.file('instance.xml') * * # validate * instance.validate_schema(schema) */ VALUE cXMLSchema; static void rxml_schema_free(xmlSchemaPtr xschema) { xmlSchemaFree(xschema); } VALUE rxml_wrap_schema(xmlSchemaPtr xschema) { return Data_Wrap_Struct(cXMLSchema, NULL, rxml_schema_free, xschema); } /* * call-seq: * XML::Schema.initialize(schema_uri) -> schema * * Create a new schema from the specified URI. */ static VALUE rxml_schema_init_from_uri(VALUE class, VALUE uri) { xmlSchemaParserCtxtPtr xparser; xmlSchemaPtr xschema; Check_Type(uri, T_STRING); xparser = xmlSchemaNewParserCtxt(StringValuePtr(uri)); xschema = xmlSchemaParse(xparser); xmlSchemaFreeParserCtxt(xparser); return Data_Wrap_Struct(cXMLSchema, NULL, rxml_schema_free, xschema); } /* * call-seq: * XML::Schema.document(document) -> schema * * Create a new schema from the specified document. */ static VALUE rxml_schema_init_from_document(VALUE class, VALUE document) { xmlDocPtr xdoc; xmlSchemaPtr xschema; xmlSchemaParserCtxtPtr xparser; Data_Get_Struct(document, xmlDoc, xdoc); xparser = xmlSchemaNewDocParserCtxt(xdoc); xschema = xmlSchemaParse(xparser); xmlSchemaFreeParserCtxt(xparser); if (xschema == NULL) return Qnil; return Data_Wrap_Struct(cXMLSchema, NULL, rxml_schema_free, xschema); } /* * call-seq: * XML::Schema.from_string("schema_data") -> "value" * * Create a new schema using the specified string. */ static VALUE rxml_schema_init_from_string(VALUE self, VALUE schema_str) { xmlSchemaParserCtxtPtr xparser; xmlSchemaPtr xschema; Check_Type(schema_str, T_STRING); xparser = xmlSchemaNewMemParserCtxt(StringValuePtr(schema_str), (int)strlen(StringValuePtr(schema_str))); xschema = xmlSchemaParse(xparser); xmlSchemaFreeParserCtxt(xparser); return Data_Wrap_Struct(cXMLSchema, NULL, rxml_schema_free, xschema); } static VALUE rxml_schema_target_namespace(VALUE self) { xmlSchemaPtr xschema; Data_Get_Struct(self, xmlSchema, xschema); QNIL_OR_STRING(xschema->targetNamespace) } static VALUE rxml_schema_name(VALUE self) { xmlSchemaPtr xschema; Data_Get_Struct(self, xmlSchema, xschema); QNIL_OR_STRING(xschema->name) } static VALUE rxml_schema_version(VALUE self) { xmlSchemaPtr xschema; Data_Get_Struct(self, xmlSchema, xschema); QNIL_OR_STRING(xschema->version) } static VALUE rxml_schema_id(VALUE self) { xmlSchemaPtr xschema; Data_Get_Struct(self, xmlSchema, xschema); QNIL_OR_STRING(xschema->id) } static VALUE rxml_schema_document(VALUE self) { xmlSchemaPtr xschema; Data_Get_Struct(self, xmlSchema, xschema); return rxml_node_wrap(xmlDocGetRootElement(xschema->doc)); } static void scan_namespaces(xmlSchemaImportPtr ximport, VALUE array, xmlChar *nsname) { xmlNodePtr xnode; xmlNsPtr xns; if (ximport->doc) { xnode = xmlDocGetRootElement(ximport->doc); xns = xnode->nsDef; while (xns) { VALUE namespace = rxml_namespace_wrap(xns); rb_ary_push(array, namespace); xns = xns->next; } } } static VALUE rxml_schema_namespaces(VALUE self) { VALUE result; xmlSchemaPtr xschema; Data_Get_Struct(self, xmlSchema, xschema); result = rb_ary_new(); xmlHashScan(xschema->schemasImports, (xmlHashScanner)scan_namespaces, (void *)result); return result; } static void scan_element(xmlSchemaElementPtr xelement, VALUE hash, xmlChar *name) { VALUE element = rxml_wrap_schema_element(xelement); rb_hash_aset(hash, rb_str_new2((const char*)name), element); } static VALUE rxml_schema_elements(VALUE self) { VALUE result = rb_hash_new(); xmlSchemaPtr xschema; Data_Get_Struct(self, xmlSchema, xschema); xmlHashScan(xschema->elemDecl, (xmlHashScanner)scan_element, (void *)result); return result; } static void scan_type(xmlSchemaTypePtr xtype, VALUE hash, xmlChar *name) { VALUE type = rxml_wrap_schema_type(xtype); rb_hash_aset(hash, rb_str_new2((const char*)name), type); } static VALUE rxml_schema_types(VALUE self) { VALUE result = rb_hash_new(); xmlSchemaPtr xschema; Data_Get_Struct(self, xmlSchema, xschema); if (xschema != NULL && xschema->typeDecl != NULL) { xmlHashScan(xschema->typeDecl, (xmlHashScanner)scan_type, (void *)result); } return result; } static void collect_imported_types(xmlSchemaImportPtr import, VALUE result) { if (import->imported && import->schema) { xmlHashScan(import->schema->typeDecl, (xmlHashScanner)scan_type, (void *)result); } } static VALUE rxml_schema_imported_types(VALUE self) { xmlSchemaPtr xschema; VALUE result = rb_hash_new(); Data_Get_Struct(self, xmlSchema, xschema); if (xschema) { xmlHashScan(xschema->schemasImports, (xmlHashScanner)collect_imported_types, (void *)result); } return result; } void rxml_init_schema(void) { cXMLSchema = rb_define_class_under(mXML, "Schema", rb_cObject); rb_define_singleton_method(cXMLSchema, "new", rxml_schema_init_from_uri, 1); rb_define_singleton_method(cXMLSchema, "from_string", rxml_schema_init_from_string, 1); rb_define_singleton_method(cXMLSchema, "document", rxml_schema_init_from_document, 1); rb_define_method(cXMLSchema, "target_namespace", rxml_schema_target_namespace, 0); rb_define_method(cXMLSchema, "name", rxml_schema_name, 0); rb_define_method(cXMLSchema, "id", rxml_schema_id, 0); rb_define_method(cXMLSchema, "version", rxml_schema_version, 0); rb_define_method(cXMLSchema, "document", rxml_schema_document, 0); rb_define_method(cXMLSchema, "elements", rxml_schema_elements, 0); rb_define_method(cXMLSchema, "imported_types", rxml_schema_imported_types, 0); rb_define_method(cXMLSchema, "namespaces", rxml_schema_namespaces, 0); rb_define_method(cXMLSchema, "types", rxml_schema_types, 0); rxml_init_schema_facet(); rxml_init_schema_element(); rxml_init_schema_attribute(); rxml_init_schema_type(); }