text: #include "ruby_libxml.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"
  
  #define UNBOUNDED 1 << 30
  #define FREE_AND_NULL(str) if ((str) != NULL) { xmlFree((xmlChar *) (str)); str = NULL; }
  
  VALUE cXMLSchemaType;
  
  static void rxml_schema_type_free(xmlSchemaTypePtr xschema_type)
  {
    xschema_type = NULL;
    xmlFree(xschema_type);
  }
  
  VALUE rxml_wrap_schema_type(xmlSchemaTypePtr xtype)
  {
    return Data_Wrap_Struct(cXMLSchemaType, NULL, rxml_schema_type_free, xtype);
  }
  
  static VALUE rxml_schema_type_namespace(VALUE self)
  {
    xmlSchemaTypePtr xtype;
  
    Data_Get_Struct(self, xmlSchemaType, xtype);
  
    QNIL_OR_STRING(xtype->targetNamespace)
  }
  
  static VALUE rxml_schema_type_name(VALUE self)
  {
    xmlSchemaTypePtr xtype;
  
    Data_Get_Struct(self, xmlSchemaType, xtype);
  
    QNIL_OR_STRING(xtype->name)
  }
  
  static VALUE rxml_schema_type_base(VALUE self)
  {
    xmlSchemaTypePtr xtype;
  
    Data_Get_Struct(self, xmlSchemaType, xtype);
  
    return Data_Wrap_Struct(cXMLSchemaType, NULL, rxml_schema_type_free, xtype->baseType);
  }
  
  static VALUE rxml_schema_type_facets(VALUE self)
  {
    xmlSchemaTypePtr xtype;
    xmlSchemaFacetPtr xfacet;
    VALUE result = rb_ary_new();
    VALUE facet;
  
    Data_Get_Struct(self, xmlSchemaType, xtype);
  
    xfacet = xtype->facets;
  
    while (xfacet != NULL)
    {
      facet = rxml_wrap_schema_facet((xmlSchemaFacetPtr)xfacet);
      rb_ary_push(result, facet);
      xfacet = xfacet->next;
    }
  
    return result;
  }
  
  static VALUE rxml_schema_type_node(VALUE self)
  {
    xmlSchemaTypePtr xtype;
  
    Data_Get_Struct(self, xmlSchemaType, xtype);
  
    if(xtype->node != NULL)
      return rxml_node_wrap(xtype->node);
    else
      return Qnil;
  }
  
  static VALUE rxml_schema_type_kind(VALUE self)
  {
    xmlSchemaTypePtr xtype;
  
    Data_Get_Struct(self, xmlSchemaType, xtype);
  
    return INT2NUM(xtype->type);
  }
  
  static VALUE rxml_schema_type_annot(VALUE self)
  {
    VALUE result = Qnil;
    xmlSchemaTypePtr xtype;
  
    Data_Get_Struct(self, xmlSchemaType, xtype);
  
    if(xtype != NULL && xtype->annot != NULL && xtype->annot->content != NULL)
    {
      xmlChar *content = xmlNodeGetContent(xtype->annot->content);
  	if (content)
  	{
  	  result = rxml_new_cstr(content, NULL);
  	  xmlFree(content);
      }
    }
    return result;
  }
  
  static void rxmlSchemaCollectElements(xmlSchemaParticlePtr xparticle, VALUE hash)
  {
    VALUE element;
    xmlSchemaTreeItemPtr xterm;
  
    if (xparticle == NULL)
      return;
  
    xterm = xparticle->children;
  
    if (xterm != NULL)
    {
      switch (xterm->type)
  	{
        case XML_SCHEMA_TYPE_ELEMENT:
          element = rxml_wrap_schema_element((xmlSchemaElementPtr)xterm);
          rb_iv_set(element, "@min", INT2NUM(xparticle->minOccurs));
  
          if (xparticle->maxOccurs >= UNBOUNDED)
            rb_iv_set(element, "@max", rb_const_get(rb_path2class("Float"), rb_intern("INFINITY")));
          else
            rb_iv_set(element, "@max", INT2NUM(xparticle->maxOccurs));
  
          if (xparticle->annot != NULL)
          {
            xmlChar *content = xmlNodeGetContent(xparticle->annot->content);
  
            if (content != NULL)
            {
              rb_iv_set(element, "@annotation", rb_str_new2((const char *) content));
              xmlFree(content);
            }
          }
  
          rb_hash_aset(hash, rb_str_new2((const char *) ((xmlSchemaElementPtr)xterm)->name), element);
          break;
  
        case XML_SCHEMA_TYPE_SEQUENCE:
          break;
  
        case XML_SCHEMA_TYPE_CHOICE:
          break;
  
        case XML_SCHEMA_TYPE_ALL:
          break;
  
        case XML_SCHEMA_TYPE_ANY:
          break;
  
        default:
          return;
      }
    }
  
    if (xterm &&
        ((xterm->type == XML_SCHEMA_TYPE_SEQUENCE) || (xterm->type == XML_SCHEMA_TYPE_CHOICE) || (xterm->type == XML_SCHEMA_TYPE_ALL)) &&
        (xterm->children != NULL))
    {
      rxmlSchemaCollectElements((xmlSchemaParticlePtr)xterm->children, hash);
    }
  
    if (xparticle->next != NULL)
    {
  	rxmlSchemaCollectElements((xmlSchemaParticlePtr)xparticle->next, hash);
    }
  }
  
  static VALUE rxml_schema_type_elements(VALUE self)
  {
    VALUE result = rb_hash_new();
    xmlSchemaTypePtr xtype;
  
    Data_Get_Struct(self, xmlSchemaType, xtype);
    rxmlSchemaCollectElements((xmlSchemaParticlePtr) xtype->subtypes, result);
  
    return result;
  }
  
  static VALUE rxml_schema_type_attributes(VALUE self)
  {
    VALUE result = rb_ary_new();
    xmlSchemaTypePtr xtype;
    xmlSchemaAttributeUsePtr xuse;
    xmlSchemaItemListPtr xuses;
    int i;
  
    Data_Get_Struct(self, xmlSchemaType, xtype);
    xuses = xtype->attrUses;
  
    if (xuses != NULL)
    {
      for (i = 0; i < xuses->nbItems; i++)
  	{
        xuse = (xmlSchemaAttributeUsePtr)xuses->items[i];
        rb_ary_push(result, rxml_wrap_schema_attribute(xuse));
      }
    }
  
    return result;
  }
  
  void rxml_init_schema_type(void)
  {
    /* Add in infinity support for ruby 1.8.7 */
    #if !defined(RUBY_VM) && defined(INFINITY)
    ID infinityId = rb_intern("INFINITY");
    if (rb_const_defined(rb_cFloat, infinityId) == Qfalse)
      rb_define_const(rb_cFloat, "INFINITY", rb_float_new(INFINITY));
    #endif
  
    cXMLSchemaType = rb_define_class_under(cXMLSchema, "Type", rb_cObject);
  
    rb_define_method(cXMLSchemaType, "namespace", rxml_schema_type_namespace, 0);
    rb_define_method(cXMLSchemaType, "name", rxml_schema_type_name, 0);
    rb_define_method(cXMLSchemaType, "elements", rxml_schema_type_elements, 0);
    rb_define_method(cXMLSchemaType, "attributes", rxml_schema_type_attributes, 0);
    rb_define_method(cXMLSchemaType, "base", rxml_schema_type_base, 0);
    rb_define_method(cXMLSchemaType, "kind", rxml_schema_type_kind, 0);
    rb_define_method(cXMLSchemaType, "node", rxml_schema_type_node, 0);
    rb_define_method(cXMLSchemaType, "facets", rxml_schema_type_facets, 0);
    rb_define_method(cXMLSchemaType, "annotation", rxml_schema_type_annot, 0);
  }
  