Back to index

php5  5.3.10
php_schema.c
Go to the documentation of this file.
00001 /*
00002   +----------------------------------------------------------------------+
00003   | PHP Version 5                                                        |
00004   +----------------------------------------------------------------------+
00005   | Copyright (c) 1997-2012 The PHP Group                                |
00006   +----------------------------------------------------------------------+
00007   | This source file is subject to version 3.01 of the PHP license,      |
00008   | that is bundled with this package in the file LICENSE, and is        |
00009   | available through the world-wide-web at the following url:           |
00010   | http://www.php.net/license/3_01.txt                                  |
00011   | If you did not receive a copy of the PHP license and are unable to   |
00012   | obtain it through the world-wide-web, please send a note to          |
00013   | license@php.net so we can mail you a copy immediately.               |
00014   +----------------------------------------------------------------------+
00015   | Authors: Brad Lafountain <rodif_bl@yahoo.com>                        |
00016   |          Shane Caraveo <shane@caraveo.com>                           |
00017   |          Dmitry Stogov <dmitry@zend.com>                             |
00018   +----------------------------------------------------------------------+
00019 */
00020 /* $Id: php_schema.c 321634 2012-01-01 13:15:04Z felipe $ */
00021 
00022 #include "php_soap.h"
00023 #include "libxml/uri.h"
00024 
00025 static int schema_simpleType(sdlPtr sdl, xmlAttrPtr tns, xmlNodePtr simpleType, sdlTypePtr cur_type);
00026 static int schema_complexType(sdlPtr sdl, xmlAttrPtr tns, xmlNodePtr compType, sdlTypePtr cur_type);
00027 static int schema_list(sdlPtr sdl, xmlAttrPtr tns, xmlNodePtr listType, sdlTypePtr cur_type);
00028 static int schema_union(sdlPtr sdl, xmlAttrPtr tns, xmlNodePtr unionType, sdlTypePtr cur_type);
00029 static int schema_simpleContent(sdlPtr sdl, xmlAttrPtr tns, xmlNodePtr simpCompType, sdlTypePtr cur_type);
00030 static int schema_restriction_simpleContent(sdlPtr sdl, xmlAttrPtr tns, xmlNodePtr restType, sdlTypePtr cur_type, int simpleType);
00031 static int schema_restriction_complexContent(sdlPtr sdl, xmlAttrPtr tns, xmlNodePtr restType, sdlTypePtr cur_type);
00032 static int schema_extension_simpleContent(sdlPtr sdl, xmlAttrPtr tns, xmlNodePtr extType, sdlTypePtr cur_type);
00033 static int schema_extension_complexContent(sdlPtr sdl, xmlAttrPtr tns, xmlNodePtr extType, sdlTypePtr cur_type);
00034 static int schema_sequence(sdlPtr sdl, xmlAttrPtr tns, xmlNodePtr seqType, sdlTypePtr cur_type, sdlContentModelPtr model);
00035 static int schema_all(sdlPtr sdl, xmlAttrPtr tns, xmlNodePtr extType, sdlTypePtr cur_type, sdlContentModelPtr model);
00036 static int schema_choice(sdlPtr sdl, xmlAttrPtr tns, xmlNodePtr choiceType, sdlTypePtr cur_type, sdlContentModelPtr model);
00037 static int schema_group(sdlPtr sdl, xmlAttrPtr tns, xmlNodePtr groupType, sdlTypePtr cur_type, sdlContentModelPtr model);
00038 static int schema_any(sdlPtr sdl, xmlAttrPtr tns, xmlNodePtr extType, sdlTypePtr cur_type, sdlContentModelPtr model);
00039 static int schema_element(sdlPtr sdl, xmlAttrPtr tns, xmlNodePtr element, sdlTypePtr cur_type, sdlContentModelPtr model);
00040 static int schema_attribute(sdlPtr sdl, xmlAttrPtr tns, xmlNodePtr attrType, sdlTypePtr cur_type, sdlCtx *ctx);
00041 static int schema_attributeGroup(sdlPtr sdl, xmlAttrPtr tns, xmlNodePtr attrType, sdlTypePtr cur_type, sdlCtx *ctx);
00042 
00043 static int schema_restriction_var_int(xmlNodePtr val, sdlRestrictionIntPtr *valptr);
00044 
00045 static int schema_restriction_var_char(xmlNodePtr val, sdlRestrictionCharPtr *valptr);
00046 
00047 static void schema_type_fixup(sdlCtx *ctx, sdlTypePtr type);
00048 
00049 static encodePtr create_encoder(sdlPtr sdl, sdlTypePtr cur_type, const xmlChar *ns, const xmlChar *type)
00050 {
00051        smart_str nscat = {0};
00052        encodePtr enc, *enc_ptr;
00053 
00054        if (sdl->encoders == NULL) {
00055               sdl->encoders = emalloc(sizeof(HashTable));
00056               zend_hash_init(sdl->encoders, 0, NULL, delete_encoder, 0);
00057        }
00058        smart_str_appends(&nscat, (char*)ns);
00059        smart_str_appendc(&nscat, ':');
00060        smart_str_appends(&nscat, (char*)type);
00061        smart_str_0(&nscat);
00062        if (zend_hash_find(sdl->encoders, nscat.c, nscat.len + 1, (void**)&enc_ptr) == SUCCESS) {
00063               enc = *enc_ptr;
00064               if (enc->details.ns) {
00065                      efree(enc->details.ns);
00066               }
00067               if (enc->details.type_str) {
00068                      efree(enc->details.type_str);
00069               }
00070        } else {
00071               enc_ptr = NULL;
00072               enc = emalloc(sizeof(encode));
00073        }
00074        memset(enc, 0, sizeof(encode));
00075 
00076        enc->details.ns = estrdup((char*)ns);
00077        enc->details.type_str = estrdup((char*)type);
00078        enc->details.sdl_type = cur_type;
00079        enc->to_xml = sdl_guess_convert_xml;
00080        enc->to_zval = sdl_guess_convert_zval;
00081 
00082        if (enc_ptr == NULL) {
00083               zend_hash_update(sdl->encoders, nscat.c, nscat.len + 1, &enc, sizeof(encodePtr), NULL);
00084        }
00085        smart_str_free(&nscat);
00086        return enc;
00087 }
00088 
00089 static encodePtr get_create_encoder(sdlPtr sdl, sdlTypePtr cur_type, const xmlChar *ns, const xmlChar *type)
00090 {
00091        encodePtr enc = get_encoder(sdl, (char*)ns, (char*)type);
00092        if (enc == NULL) {
00093               enc = create_encoder(sdl, cur_type, ns, type);
00094        }
00095        return enc;
00096 }
00097 
00098 static void schema_load_file(sdlCtx *ctx, xmlAttrPtr ns, xmlChar *location, xmlAttrPtr tns, int import TSRMLS_DC) {
00099        if (location != NULL &&
00100            !zend_hash_exists(&ctx->docs, (char*)location, xmlStrlen(location)+1)) {
00101               xmlDocPtr doc;
00102               xmlNodePtr schema;
00103               xmlAttrPtr new_tns;
00104 
00105               sdl_set_uri_credentials(ctx, (char*)location TSRMLS_CC);
00106               doc = soap_xmlParseFile((char*)location TSRMLS_CC);
00107               sdl_restore_uri_credentials(ctx TSRMLS_CC);
00108 
00109               if (doc == NULL) {
00110                      soap_error1(E_ERROR, "Parsing Schema: can't import schema from '%s'", location);
00111               }
00112               schema = get_node(doc->children, "schema");
00113               if (schema == NULL) {
00114                      xmlFreeDoc(doc);
00115                      soap_error1(E_ERROR, "Parsing Schema: can't import schema from '%s'", location);
00116               }
00117               new_tns = get_attribute(schema->properties, "targetNamespace");
00118               if (import) {
00119                      if (ns != NULL && (new_tns == NULL || xmlStrcmp(ns->children->content, new_tns->children->content) != 0)) {
00120                             xmlFreeDoc(doc);
00121                             soap_error2(E_ERROR, "Parsing Schema: can't import schema from '%s', unexpected 'targetNamespace'='%s'", location, ns->children->content);
00122                      }
00123                      if (ns == NULL && new_tns != NULL) {
00124                             xmlFreeDoc(doc);
00125                             soap_error2(E_ERROR, "Parsing Schema: can't import schema from '%s', unexpected 'targetNamespace'='%s'", location, new_tns->children->content);
00126                      }
00127               } else {
00128                      new_tns = get_attribute(schema->properties, "targetNamespace");
00129                      if (new_tns == NULL) {
00130                             if (tns != NULL) {
00131                                    xmlSetProp(schema, BAD_CAST("targetNamespace"), tns->children->content);
00132                             }
00133                      } else if (tns != NULL && xmlStrcmp(tns->children->content, new_tns->children->content) != 0) {
00134                             xmlFreeDoc(doc);
00135                             soap_error1(E_ERROR, "Parsing Schema: can't include schema from '%s', different 'targetNamespace'", location);
00136                      }
00137               }
00138               zend_hash_add(&ctx->docs, (char*)location, xmlStrlen(location)+1, (void**)&doc, sizeof(xmlDocPtr), NULL);
00139               load_schema(ctx, schema TSRMLS_CC);
00140        }
00141 }
00142 
00143 /*
00144 2.6.1 xsi:type
00145 2.6.2 xsi:nil
00146 2.6.3 xsi:schemaLocation, xsi:noNamespaceSchemaLocation
00147 */
00148 
00149 /*
00150 <schema
00151   attributeFormDefault = (qualified | unqualified) : unqualified
00152   blockDefault = (#all | List of (extension | restriction | substitution))  : ''
00153   elementFormDefault = (qualified | unqualified) : unqualified
00154   finalDefault = (#all | List of (extension | restriction))  : ''
00155   id = ID
00156   targetNamespace = anyURI
00157   version = token
00158   xml:lang = language
00159   {any attributes with non-schema namespace . . .}>
00160   Content: ((include | import | redefine | annotation)*, (((simpleType | complexType | group | attributeGroup) | element | attribute | notation), annotation*)*)
00161 </schema>
00162 */
00163 int load_schema(sdlCtx *ctx, xmlNodePtr schema TSRMLS_DC)
00164 {
00165        xmlNodePtr trav;
00166        xmlAttrPtr tns;
00167 
00168        if (!ctx->sdl->types) {
00169               ctx->sdl->types = emalloc(sizeof(HashTable));
00170               zend_hash_init(ctx->sdl->types, 0, NULL, delete_type, 0);
00171        }
00172        if (!ctx->attributes) {
00173               ctx->attributes = emalloc(sizeof(HashTable));
00174               zend_hash_init(ctx->attributes, 0, NULL, delete_attribute, 0);
00175        }
00176        if (!ctx->attributeGroups) {
00177               ctx->attributeGroups = emalloc(sizeof(HashTable));
00178               zend_hash_init(ctx->attributeGroups, 0, NULL, delete_type, 0);
00179        }
00180 
00181        tns = get_attribute(schema->properties, "targetNamespace");
00182        if (tns == NULL) {
00183               tns = xmlSetProp(schema, BAD_CAST("targetNamespace"), BAD_CAST(""));
00184               xmlNewNs(schema, BAD_CAST(""), NULL);
00185        }
00186 
00187        trav = schema->children;
00188        while (trav != NULL) {
00189               if (node_is_equal(trav,"include")) {
00190                      xmlAttrPtr location;
00191 
00192                      location = get_attribute(trav->properties, "schemaLocation");
00193                      if (location == NULL) {
00194                             soap_error0(E_ERROR, "Parsing Schema: include has no 'schemaLocation' attribute");
00195                      } else {
00196                             xmlChar *uri;
00197                             xmlChar *base = xmlNodeGetBase(trav->doc, trav);
00198 
00199                             if (base == NULL) {
00200                          uri = xmlBuildURI(location->children->content, trav->doc->URL);
00201                             } else {
00202                      uri = xmlBuildURI(location->children->content, base);
00203                          xmlFree(base);
00204                             }
00205                             schema_load_file(ctx, NULL, uri, tns, 0 TSRMLS_CC);
00206                             xmlFree(uri);
00207                      }
00208 
00209               } else if (node_is_equal(trav,"redefine")) {
00210                      xmlAttrPtr location;
00211 
00212                      location = get_attribute(trav->properties, "schemaLocation");
00213                      if (location == NULL) {
00214                             soap_error0(E_ERROR, "Parsing Schema: redefine has no 'schemaLocation' attribute");
00215                      } else {
00216                        xmlChar *uri;
00217                             xmlChar *base = xmlNodeGetBase(trav->doc, trav);
00218 
00219                             if (base == NULL) {
00220                          uri = xmlBuildURI(location->children->content, trav->doc->URL);
00221                             } else {
00222                      uri = xmlBuildURI(location->children->content, base);
00223                          xmlFree(base);
00224                             }
00225                             schema_load_file(ctx, NULL, uri, tns, 0 TSRMLS_CC);
00226                             xmlFree(uri);
00227                             /* TODO: <redefine> support */
00228                      }
00229 
00230               } else if (node_is_equal(trav,"import")) {
00231                      xmlAttrPtr ns, location;
00232                      xmlChar *uri = NULL;
00233 
00234                      ns = get_attribute(trav->properties, "namespace");
00235                      location = get_attribute(trav->properties, "schemaLocation");
00236 
00237                      if (ns != NULL && tns != NULL && xmlStrcmp(ns->children->content, tns->children->content) == 0) {
00238                             if (location) {
00239                                    soap_error1(E_ERROR, "Parsing Schema: can't import schema from '%s', namespace must not match the enclosing schema 'targetNamespace'", location->children->content);
00240                             } else {
00241                                    soap_error0(E_ERROR, "Parsing Schema: can't import schema. Namespace must not match the enclosing schema 'targetNamespace'");
00242                             }
00243                      }
00244                      if (location) {
00245                             xmlChar *base = xmlNodeGetBase(trav->doc, trav);
00246 
00247                             if (base == NULL) {
00248                          uri = xmlBuildURI(location->children->content, trav->doc->URL);
00249                             } else {
00250                      uri = xmlBuildURI(location->children->content, base);
00251                          xmlFree(base);
00252                             }
00253                      }
00254                      schema_load_file(ctx, ns, uri, tns, 1 TSRMLS_CC);
00255                      if (uri != NULL) {xmlFree(uri);}
00256               } else if (node_is_equal(trav,"annotation")) {
00257                      /* TODO: <annotation> support */
00258 /* annotation cleanup
00259                      xmlNodePtr tmp = trav;
00260                      trav = trav->next;
00261                      xmlUnlinkNode(tmp);
00262                      xmlFreeNode(tmp);
00263                      continue;
00264 */
00265               } else {
00266                      break;
00267               }
00268               trav = trav->next;
00269        }
00270 
00271        while (trav != NULL) {
00272               if (node_is_equal(trav,"simpleType")) {
00273                      schema_simpleType(ctx->sdl, tns, trav, NULL);
00274               } else if (node_is_equal(trav,"complexType")) {
00275                      schema_complexType(ctx->sdl, tns, trav, NULL);
00276               } else if (node_is_equal(trav,"group")) {
00277                      schema_group(ctx->sdl, tns, trav, NULL, NULL);
00278               } else if (node_is_equal(trav,"attributeGroup")) {
00279                      schema_attributeGroup(ctx->sdl, tns, trav, NULL, ctx);
00280               } else if (node_is_equal(trav,"element")) {
00281                      schema_element(ctx->sdl, tns, trav, NULL, NULL);
00282               } else if (node_is_equal(trav,"attribute")) {
00283                      schema_attribute(ctx->sdl, tns, trav, NULL, ctx);
00284               } else if (node_is_equal(trav,"notation")) {
00285                      /* TODO: <notation> support */
00286               } else if (node_is_equal(trav,"annotation")) {
00287                      /* TODO: <annotation> support */
00288               } else {
00289                      soap_error1(E_ERROR, "Parsing Schema: unexpected <%s> in schema", trav->name);
00290               }
00291               trav = trav->next;
00292        }
00293        return TRUE;
00294 }
00295 
00296 /*
00297 <simpleType
00298   final = (#all | (list | union | restriction))
00299   id = ID
00300   name = NCName
00301   {any attributes with non-schema namespace . . .}>
00302   Content: (annotation?, (restriction | list | union))
00303 </simpleType>
00304 */
00305 static int schema_simpleType(sdlPtr sdl, xmlAttrPtr tns, xmlNodePtr simpleType, sdlTypePtr cur_type)
00306 {
00307        xmlNodePtr trav;
00308        xmlAttrPtr name, ns;
00309 
00310        ns = get_attribute(simpleType->properties, "targetNamespace");
00311        if (ns == NULL) {
00312               ns = tns;
00313        }
00314 
00315        name = get_attribute(simpleType->properties, "name");
00316        if (cur_type != NULL) {
00317               /* Anonymous type inside <element> or <restriction> */
00318               sdlTypePtr newType, *ptr;
00319 
00320               newType = emalloc(sizeof(sdlType));
00321               memset(newType, 0, sizeof(sdlType));
00322               newType->kind = XSD_TYPEKIND_SIMPLE;
00323               if (name != NULL) {
00324                      newType->name = estrdup((char*)name->children->content);
00325                      newType->namens = estrdup((char*)ns->children->content);
00326               } else {
00327                      newType->name = estrdup(cur_type->name);
00328                      newType->namens = estrdup(cur_type->namens);
00329               }
00330 
00331               zend_hash_next_index_insert(sdl->types,  &newType, sizeof(sdlTypePtr), (void **)&ptr);
00332 
00333               if (sdl->encoders == NULL) {
00334                      sdl->encoders = emalloc(sizeof(HashTable));
00335                      zend_hash_init(sdl->encoders, 0, NULL, delete_encoder, 0);
00336               }
00337               cur_type->encode = emalloc(sizeof(encode));
00338               memset(cur_type->encode, 0, sizeof(encode));
00339               cur_type->encode->details.ns = estrdup(newType->namens);
00340               cur_type->encode->details.type_str = estrdup(newType->name);
00341               cur_type->encode->details.sdl_type = *ptr;
00342               cur_type->encode->to_xml = sdl_guess_convert_xml;
00343               cur_type->encode->to_zval = sdl_guess_convert_zval;
00344               zend_hash_next_index_insert(sdl->encoders,  &cur_type->encode, sizeof(encodePtr), NULL);
00345 
00346               cur_type =*ptr;
00347 
00348        } else if (name != NULL) {
00349               sdlTypePtr newType, *ptr;
00350 
00351               newType = emalloc(sizeof(sdlType));
00352               memset(newType, 0, sizeof(sdlType));
00353               newType->kind = XSD_TYPEKIND_SIMPLE;
00354               newType->name = estrdup((char*)name->children->content);
00355               newType->namens = estrdup((char*)ns->children->content);
00356 
00357               if (cur_type == NULL) {
00358                      zend_hash_next_index_insert(sdl->types,  &newType, sizeof(sdlTypePtr), (void **)&ptr);
00359               } else {
00360                      if (cur_type->elements == NULL) {
00361                             cur_type->elements = emalloc(sizeof(HashTable));
00362                             zend_hash_init(cur_type->elements, 0, NULL, delete_type, 0);
00363                      }
00364                      zend_hash_update(cur_type->elements, newType->name, strlen(newType->name)+1, &newType, sizeof(sdlTypePtr), (void **)&ptr);
00365               }
00366               cur_type = (*ptr);
00367 
00368               create_encoder(sdl, cur_type, ns->children->content, name->children->content);
00369        } else {
00370               soap_error0(E_ERROR, "Parsing Schema: simpleType has no 'name' attribute");
00371        }
00372 
00373        trav = simpleType->children;
00374        if (trav != NULL && node_is_equal(trav,"annotation")) {
00375               /* TODO: <annotation> support */
00376               trav = trav->next;
00377        }
00378        if (trav != NULL) {
00379               if (node_is_equal(trav,"restriction")) {
00380                      schema_restriction_simpleContent(sdl, tns, trav, cur_type, 1);
00381                      trav = trav->next;
00382               } else if (node_is_equal(trav,"list")) {
00383                      cur_type->kind = XSD_TYPEKIND_LIST;
00384                      schema_list(sdl, tns, trav, cur_type);
00385                      trav = trav->next;
00386               } else if (node_is_equal(trav,"union")) {
00387                      cur_type->kind = XSD_TYPEKIND_UNION;
00388                      schema_union(sdl, tns, trav, cur_type);
00389                      trav = trav->next;
00390               } else {
00391                      soap_error1(E_ERROR, "Parsing Schema: unexpected <%s> in simpleType", trav->name);
00392               }
00393        } else {
00394               soap_error0(E_ERROR, "Parsing Schema: expected <restriction>, <list> or <union> in simpleType");
00395        }
00396        if (trav != NULL) {
00397               soap_error1(E_ERROR, "Parsing Schema: unexpected <%s> in simpleType", trav->name);
00398        }
00399 
00400        return TRUE;
00401 }
00402 
00403 /*
00404 <list
00405   id = ID
00406   itemType = QName
00407   {any attributes with non-schema namespace . . .}>
00408   Content: (annotation?, (simpleType?))
00409 </list>
00410 */
00411 static int schema_list(sdlPtr sdl, xmlAttrPtr tns, xmlNodePtr listType, sdlTypePtr cur_type)
00412 {
00413        xmlNodePtr trav;
00414        xmlAttrPtr itemType;
00415 
00416        itemType = get_attribute(listType->properties, "itemType");
00417        if (itemType != NULL) {
00418               char *type, *ns;
00419               xmlNsPtr nsptr;
00420 
00421               parse_namespace(itemType->children->content, &type, &ns);
00422               nsptr = xmlSearchNs(listType->doc, listType, BAD_CAST(ns));
00423               if (nsptr != NULL) {
00424                      sdlTypePtr newType, *tmp;
00425 
00426                      newType = emalloc(sizeof(sdlType));
00427                      memset(newType, 0, sizeof(sdlType));
00428 
00429                      newType->name = estrdup(type);
00430                      newType->namens = estrdup((char*)nsptr->href);
00431 
00432                      newType->encode = get_create_encoder(sdl, newType, nsptr->href, BAD_CAST(type));
00433 
00434                      if (cur_type->elements == NULL) {
00435                             cur_type->elements = emalloc(sizeof(HashTable));
00436                             zend_hash_init(cur_type->elements, 0, NULL, delete_type, 0);
00437                      }
00438                      zend_hash_next_index_insert(cur_type->elements, &newType, sizeof(sdlTypePtr), (void **)&tmp);
00439               }
00440               if (type) {efree(type);}
00441               if (ns) {efree(ns);}
00442        }
00443 
00444        trav = listType->children;
00445        if (trav != NULL && node_is_equal(trav,"annotation")) {
00446               /* TODO: <annotation> support */
00447               trav = trav->next;
00448        }
00449        if (trav != NULL && node_is_equal(trav,"simpleType")) {
00450               sdlTypePtr newType, *tmp;
00451 
00452               if (itemType != NULL) {
00453                      soap_error0(E_ERROR, "Parsing Schema: element has both 'itemType' attribute and subtype");
00454               }
00455 
00456               newType = emalloc(sizeof(sdlType));
00457               memset(newType, 0, sizeof(sdlType));
00458 
00459               {
00460                      smart_str anonymous = {0};
00461                      
00462                      smart_str_appendl(&anonymous, "anonymous", sizeof("anonymous")-1);
00463                      smart_str_append_long(&anonymous, zend_hash_num_elements(sdl->types));
00464                      smart_str_0(&anonymous);
00465                      newType->name = anonymous.c;
00466               }
00467               newType->namens = estrdup((char*)tns->children->content);
00468 
00469               if (cur_type->elements == NULL) {
00470                      cur_type->elements = emalloc(sizeof(HashTable));
00471                      zend_hash_init(cur_type->elements, 0, NULL, delete_type, 0);
00472               }
00473               zend_hash_next_index_insert(cur_type->elements, &newType, sizeof(sdlTypePtr), (void **)&tmp);
00474 
00475               schema_simpleType(sdl, tns, trav, newType);
00476 
00477               trav = trav->next;
00478        }
00479        if (trav != NULL) {
00480               soap_error1(E_ERROR, "Parsing Schema: unexpected <%s> in list", trav->name);
00481        }
00482        return TRUE;
00483 }
00484 
00485 /*
00486 <union
00487   id = ID
00488   memberTypes = List of QName
00489   {any attributes with non-schema namespace . . .}>
00490   Content: (annotation?, (simpleType*))
00491 </union>
00492 */
00493 static int schema_union(sdlPtr sdl, xmlAttrPtr tns, xmlNodePtr unionType, sdlTypePtr cur_type)
00494 {
00495        xmlNodePtr trav;
00496        xmlAttrPtr memberTypes;
00497 
00498        memberTypes = get_attribute(unionType->properties, "memberTypes");
00499        if (memberTypes != NULL) {
00500               char *str, *start, *end, *next;
00501               char *type, *ns;
00502               xmlNsPtr nsptr;
00503 
00504               str = estrdup((char*)memberTypes->children->content);
00505               whiteSpace_collapse(BAD_CAST(str));
00506               start = str;
00507               while (start != NULL && *start != '\0') {
00508                      end = strchr(start,' ');
00509                      if (end == NULL) {
00510                             next = NULL;
00511                      } else {
00512                             *end = '\0';
00513                             next = end+1;
00514                      }
00515 
00516                      parse_namespace(BAD_CAST(start), &type, &ns);
00517                      nsptr = xmlSearchNs(unionType->doc, unionType, BAD_CAST(ns));
00518                      if (nsptr != NULL) {
00519                             sdlTypePtr newType, *tmp;
00520 
00521                             newType = emalloc(sizeof(sdlType));
00522                             memset(newType, 0, sizeof(sdlType));
00523 
00524                             newType->name = estrdup(type);
00525                             newType->namens = estrdup((char*)nsptr->href);
00526 
00527                             newType->encode = get_create_encoder(sdl, newType, nsptr->href, BAD_CAST(type));
00528 
00529                             if (cur_type->elements == NULL) {
00530                                    cur_type->elements = emalloc(sizeof(HashTable));
00531                                    zend_hash_init(cur_type->elements, 0, NULL, delete_type, 0);
00532                             }
00533                             zend_hash_next_index_insert(cur_type->elements, &newType, sizeof(sdlTypePtr), (void **)&tmp);
00534                      }
00535                      if (type) {efree(type);}
00536                      if (ns) {efree(ns);}
00537 
00538                      start = next;
00539               }
00540               efree(str);
00541        }
00542 
00543        trav = unionType->children;
00544        if (trav != NULL && node_is_equal(trav,"annotation")) {
00545               /* TODO: <annotation> support */
00546               trav = trav->next;
00547        }
00548        while (trav != NULL) {
00549               if (node_is_equal(trav,"simpleType")) {
00550                      sdlTypePtr newType, *tmp;
00551 
00552                      newType = emalloc(sizeof(sdlType));
00553                      memset(newType, 0, sizeof(sdlType));
00554 
00555                      {
00556                             smart_str anonymous = {0};
00557                      
00558                             smart_str_appendl(&anonymous, "anonymous", sizeof("anonymous")-1);
00559                             smart_str_append_long(&anonymous, zend_hash_num_elements(sdl->types));
00560                             smart_str_0(&anonymous);
00561                             newType->name = anonymous.c;
00562                      }
00563                      newType->namens = estrdup((char*)tns->children->content);
00564 
00565                      if (cur_type->elements == NULL) {
00566                             cur_type->elements = emalloc(sizeof(HashTable));
00567                             zend_hash_init(cur_type->elements, 0, NULL, delete_type, 0);
00568                      }
00569                      zend_hash_next_index_insert(cur_type->elements, &newType, sizeof(sdlTypePtr), (void **)&tmp);
00570 
00571                      schema_simpleType(sdl, tns, trav, newType);
00572 
00573               } else {
00574                      soap_error1(E_ERROR, "Parsing Schema: unexpected <%s> in union", trav->name);
00575               }
00576               trav = trav->next;
00577        }
00578        if (trav != NULL) {
00579               soap_error1(E_ERROR, "Parsing Schema: unexpected <%s> in union", trav->name);
00580        }
00581        return TRUE;
00582 }
00583 
00584 /*
00585 <simpleContent
00586   id = ID
00587   {any attributes with non-schema namespace . . .}>
00588   Content: (annotation?, (restriction | extension))
00589 </simpleContent>
00590 */
00591 static int schema_simpleContent(sdlPtr sdl, xmlAttrPtr tns, xmlNodePtr simpCompType, sdlTypePtr cur_type)
00592 {
00593        xmlNodePtr trav;
00594 
00595        trav = simpCompType->children;
00596        if (trav != NULL && node_is_equal(trav,"annotation")) {
00597               /* TODO: <annotation> support */
00598               trav = trav->next;
00599        }
00600        if (trav != NULL) {
00601               if (node_is_equal(trav, "restriction")) {
00602                      cur_type->kind = XSD_TYPEKIND_RESTRICTION;
00603                      schema_restriction_simpleContent(sdl, tns, trav, cur_type, 0);
00604                      trav = trav->next;
00605               } else if (node_is_equal(trav, "extension")) {
00606                      cur_type->kind = XSD_TYPEKIND_EXTENSION;
00607                      schema_extension_simpleContent(sdl, tns, trav, cur_type);
00608                      trav = trav->next;
00609               } else {
00610                      soap_error1(E_ERROR, "Parsing Schema: unexpected <%s> in simpleContent", trav->name);
00611               }
00612        } else {
00613               soap_error0(E_ERROR, "Parsing Schema: expected <restriction> or <extension> in simpleContent");
00614        }
00615        if (trav != NULL) {
00616               soap_error1(E_ERROR, "Parsing Schema: unexpected <%s> in simpleContent", trav->name);
00617        }
00618 
00619        return TRUE;
00620 }
00621 
00622 /*
00623 simpleType:<restriction
00624   base = QName
00625   id = ID
00626   {any attributes with non-schema namespace . . .}>
00627   Content: (annotation?, (simpleType?, (minExclusive | minInclusive | maxExclusive | maxInclusive | totalDigits | fractionDigits | length | minLength | maxLength | enumeration | whiteSpace | pattern)*)?)
00628 </restriction>
00629 simpleContent:<restriction
00630   base = QName
00631   id = ID
00632   {any attributes with non-schema namespace . . .}>
00633   Content: (annotation?, (simpleType?, (minExclusive | minInclusive | maxExclusive | maxInclusive | totalDigits | fractionDigits | length | minLength | maxLength | enumeration | whiteSpace | pattern)*)?, ((attribute | attributeGroup)*, anyAttribute?))
00634 </restriction>
00635 */
00636 static int schema_restriction_simpleContent(sdlPtr sdl, xmlAttrPtr tns, xmlNodePtr restType, sdlTypePtr cur_type, int simpleType)
00637 {
00638        xmlNodePtr trav;
00639        xmlAttrPtr base;
00640 
00641        base = get_attribute(restType->properties, "base");
00642        if (base != NULL) {
00643               char *type, *ns;
00644               xmlNsPtr nsptr;
00645 
00646               parse_namespace(base->children->content, &type, &ns);
00647               nsptr = xmlSearchNs(restType->doc, restType, BAD_CAST(ns));
00648               if (nsptr != NULL) {
00649                      cur_type->encode = get_create_encoder(sdl, cur_type, nsptr->href, BAD_CAST(type));
00650               }
00651               if (type) {efree(type);}
00652               if (ns) {efree(ns);}
00653        } else if (!simpleType) {
00654               soap_error0(E_ERROR, "Parsing Schema: restriction has no 'base' attribute");
00655        }
00656 
00657        if (cur_type->restrictions == NULL) {
00658               cur_type->restrictions = emalloc(sizeof(sdlRestrictions));
00659               memset(cur_type->restrictions, 0, sizeof(sdlRestrictions));
00660        }
00661 
00662        trav = restType->children;
00663        if (trav != NULL && node_is_equal(trav, "annotation")) {
00664               /* TODO: <annotation> support */
00665               trav = trav->next;
00666        }
00667        if (trav != NULL && node_is_equal(trav, "simpleType")) {
00668               schema_simpleType(sdl, tns, trav, cur_type);
00669               trav = trav->next;
00670        }
00671        while (trav != NULL) {
00672               if (node_is_equal(trav, "minExclusive")) {
00673                      schema_restriction_var_int(trav, &cur_type->restrictions->minExclusive);
00674               } else if (node_is_equal(trav, "minInclusive")) {
00675                      schema_restriction_var_int(trav, &cur_type->restrictions->minInclusive);
00676               } else if (node_is_equal(trav, "maxExclusive")) {
00677                      schema_restriction_var_int(trav, &cur_type->restrictions->maxExclusive);
00678               } else if (node_is_equal(trav, "maxInclusive")) {
00679                      schema_restriction_var_int(trav, &cur_type->restrictions->maxInclusive);
00680               } else if (node_is_equal(trav, "totalDigits")) {
00681                      schema_restriction_var_int(trav, &cur_type->restrictions->totalDigits);
00682               } else if (node_is_equal(trav, "fractionDigits")) {
00683                      schema_restriction_var_int(trav, &cur_type->restrictions->fractionDigits);
00684               } else if (node_is_equal(trav, "length")) {
00685                      schema_restriction_var_int(trav, &cur_type->restrictions->length);
00686               } else if (node_is_equal(trav, "minLength")) {
00687                      schema_restriction_var_int(trav, &cur_type->restrictions->minLength);
00688               } else if (node_is_equal(trav, "maxLength")) {
00689                      schema_restriction_var_int(trav, &cur_type->restrictions->maxLength);
00690               } else if (node_is_equal(trav, "whiteSpace")) {
00691                      schema_restriction_var_char(trav, &cur_type->restrictions->whiteSpace);
00692               } else if (node_is_equal(trav, "pattern")) {
00693                      schema_restriction_var_char(trav, &cur_type->restrictions->pattern);
00694               } else if (node_is_equal(trav, "enumeration")) {
00695                      sdlRestrictionCharPtr enumval = NULL;
00696 
00697                      schema_restriction_var_char(trav, &enumval);
00698                      if (cur_type->restrictions->enumeration == NULL) {
00699                             cur_type->restrictions->enumeration = emalloc(sizeof(HashTable));
00700                             zend_hash_init(cur_type->restrictions->enumeration, 0, NULL, delete_restriction_var_char, 0);
00701                      }
00702                      if (zend_hash_add(cur_type->restrictions->enumeration, enumval->value, strlen(enumval->value)+1, &enumval, sizeof(sdlRestrictionCharPtr), NULL) == FAILURE) {
00703                             delete_restriction_var_char(&enumval);
00704                      }
00705               } else {
00706                      break;
00707               }
00708               trav = trav->next;
00709        }
00710        if (!simpleType) {
00711               while (trav != NULL) {
00712                      if (node_is_equal(trav,"attribute")) {
00713                             schema_attribute(sdl, tns, trav, cur_type, NULL);
00714                      } else if (node_is_equal(trav,"attributeGroup")) {
00715                             schema_attributeGroup(sdl, tns, trav, cur_type, NULL);
00716                      } else if (node_is_equal(trav,"anyAttribute")) {
00717                             /* TODO: <anyAttribute> support */
00718                             trav = trav->next;
00719                             break;
00720                      } else {
00721                             soap_error1(E_ERROR, "Parsing Schema: unexpected <%s> in restriction", trav->name);
00722                      }
00723                      trav = trav->next;
00724               }
00725        }
00726        if (trav != NULL) {
00727               soap_error1(E_ERROR, "Parsing Schema: unexpected <%s> in restriction", trav->name);
00728        }
00729 
00730        return TRUE;
00731 }
00732 
00733 /*
00734 <restriction
00735   base = QName
00736   id = ID
00737   {any attributes with non-schema namespace . . .}>
00738   Content: (annotation?, (group | all | choice | sequence)?, ((attribute | attributeGroup)*, anyAttribute?))
00739 </restriction>
00740 */
00741 static int schema_restriction_complexContent(sdlPtr sdl, xmlAttrPtr tns, xmlNodePtr restType, sdlTypePtr cur_type)
00742 {
00743        xmlAttrPtr base;
00744        xmlNodePtr trav;
00745 
00746        base = get_attribute(restType->properties, "base");
00747        if (base != NULL) {
00748               char *type, *ns;
00749               xmlNsPtr nsptr;
00750 
00751               parse_namespace(base->children->content, &type, &ns);
00752               nsptr = xmlSearchNs(restType->doc, restType, BAD_CAST(ns));
00753               if (nsptr != NULL) {
00754                      cur_type->encode = get_create_encoder(sdl, cur_type, nsptr->href, BAD_CAST(type));
00755               }
00756               if (type) {efree(type);}
00757               if (ns) {efree(ns);}
00758        } else {
00759               soap_error0(E_ERROR, "Parsing Schema: restriction has no 'base' attribute");
00760        }
00761 
00762        trav = restType->children;
00763        if (trav != NULL && node_is_equal(trav,"annotation")) {
00764               /* TODO: <annotation> support */
00765               trav = trav->next;
00766        }
00767        if (trav != NULL) {
00768               if (node_is_equal(trav,"group")) {
00769                      schema_group(sdl, tns, trav, cur_type, NULL);
00770                      trav = trav->next;
00771               } else if (node_is_equal(trav,"all")) {
00772                      schema_all(sdl, tns, trav, cur_type, NULL);
00773                      trav = trav->next;
00774               } else if (node_is_equal(trav,"choice")) {
00775                      schema_choice(sdl, tns, trav, cur_type, NULL);
00776                      trav = trav->next;
00777               } else if (node_is_equal(trav,"sequence")) {
00778                      schema_sequence(sdl, tns, trav, cur_type, NULL);
00779                      trav = trav->next;
00780               }
00781        }
00782        while (trav != NULL) {
00783               if (node_is_equal(trav,"attribute")) {
00784                      schema_attribute(sdl, tns, trav, cur_type, NULL);
00785               } else if (node_is_equal(trav,"attributeGroup")) {
00786                      schema_attributeGroup(sdl, tns, trav, cur_type, NULL);
00787               } else if (node_is_equal(trav,"anyAttribute")) {
00788                      /* TODO: <anyAttribute> support */
00789                      trav = trav->next;
00790                      break;
00791               } else {
00792                      soap_error1(E_ERROR, "Parsing Schema: unexpected <%s> in restriction", trav->name);
00793               }
00794               trav = trav->next;
00795        }
00796        if (trav != NULL) {
00797               soap_error1(E_ERROR, "Parsing Schema: unexpected <%s> in restriction", trav->name);
00798        }
00799 
00800        return TRUE;
00801 }
00802 
00803 static int schema_restriction_var_int(xmlNodePtr val, sdlRestrictionIntPtr *valptr)
00804 {
00805        xmlAttrPtr fixed, value;
00806 
00807        if ((*valptr) == NULL) {
00808               (*valptr) = emalloc(sizeof(sdlRestrictionInt));
00809        }
00810        memset((*valptr), 0, sizeof(sdlRestrictionInt));
00811 
00812        fixed = get_attribute(val->properties, "fixed");
00813        (*valptr)->fixed = FALSE;
00814        if (fixed != NULL) {
00815               if (!strncmp((char*)fixed->children->content, "true", sizeof("true")) ||
00816                      !strncmp((char*)fixed->children->content, "1", sizeof("1")))
00817                      (*valptr)->fixed = TRUE;
00818        }
00819 
00820        value = get_attribute(val->properties, "value");
00821        if (value == NULL) {
00822               soap_error0(E_ERROR, "Parsing Schema: missing restriction value");
00823        }
00824 
00825        (*valptr)->value = atoi((char*)value->children->content);
00826 
00827        return TRUE;
00828 }
00829 
00830 static int schema_restriction_var_char(xmlNodePtr val, sdlRestrictionCharPtr *valptr)
00831 {
00832        xmlAttrPtr fixed, value;
00833 
00834        if ((*valptr) == NULL) {
00835               (*valptr) = emalloc(sizeof(sdlRestrictionChar));
00836        }
00837        memset((*valptr), 0, sizeof(sdlRestrictionChar));
00838 
00839        fixed = get_attribute(val->properties, "fixed");
00840        (*valptr)->fixed = FALSE;
00841        if (fixed != NULL) {
00842               if (!strncmp((char*)fixed->children->content, "true", sizeof("true")) ||
00843                   !strncmp((char*)fixed->children->content, "1", sizeof("1"))) {
00844                      (*valptr)->fixed = TRUE;
00845               }
00846        }
00847 
00848        value = get_attribute(val->properties, "value");
00849        if (value == NULL) {
00850               soap_error0(E_ERROR, "Parsing Schema: missing restriction value");
00851        }
00852 
00853        (*valptr)->value = estrdup((char*)value->children->content);
00854        return TRUE;
00855 }
00856 
00857 /*
00858 From simpleContent (not supported):
00859 <extension
00860   base = QName
00861   id = ID
00862   {any attributes with non-schema namespace . . .}>
00863   Content: (annotation?, ((attribute | attributeGroup)*, anyAttribute?))
00864 </extension>
00865 */
00866 static int schema_extension_simpleContent(sdlPtr sdl, xmlAttrPtr tns, xmlNodePtr extType, sdlTypePtr cur_type)
00867 {
00868        xmlNodePtr trav;
00869        xmlAttrPtr base;
00870 
00871        base = get_attribute(extType->properties, "base");
00872        if (base != NULL) {
00873               char *type, *ns;
00874               xmlNsPtr nsptr;
00875 
00876               parse_namespace(base->children->content, &type, &ns);
00877               nsptr = xmlSearchNs(extType->doc, extType, BAD_CAST(ns));
00878               if (nsptr != NULL) {
00879                      cur_type->encode = get_create_encoder(sdl, cur_type, nsptr->href, BAD_CAST(type));
00880               }
00881               if (type) {efree(type);}
00882               if (ns) {efree(ns);}
00883        } else {
00884               soap_error0(E_ERROR, "Parsing Schema: extension has no 'base' attribute");
00885        }
00886 
00887        trav = extType->children;
00888        if (trav != NULL && node_is_equal(trav,"annotation")) {
00889               /* TODO: <annotation> support */
00890               trav = trav->next;
00891        }
00892        while (trav != NULL) {
00893               if (node_is_equal(trav,"attribute")) {
00894                      schema_attribute(sdl, tns, trav, cur_type, NULL);
00895               } else if (node_is_equal(trav,"attributeGroup")) {
00896                      schema_attributeGroup(sdl, tns, trav, cur_type, NULL);
00897               } else if (node_is_equal(trav,"anyAttribute")) {
00898                      /* TODO: <anyAttribute> support */
00899                      trav = trav->next;
00900                      break;
00901               } else {
00902                      soap_error1(E_ERROR, "Parsing Schema: unexpected <%s> in extension", trav->name);
00903               }
00904               trav = trav->next;
00905        }
00906        if (trav != NULL) {
00907               soap_error1(E_ERROR, "Parsing Schema: unexpected <%s> in extension", trav->name);
00908        }
00909        return TRUE;
00910 }
00911 
00912 /*
00913 From complexContent:
00914 <extension
00915   base = QName
00916   id = ID
00917   {any attributes with non-schema namespace . . .}>
00918   Content: (annotation?, ((group | all | choice | sequence)?, ((attribute | attributeGroup)*, anyAttribute?)))
00919 </extension>
00920 */
00921 static int schema_extension_complexContent(sdlPtr sdl, xmlAttrPtr tns, xmlNodePtr extType, sdlTypePtr cur_type)
00922 {
00923        xmlNodePtr trav;
00924        xmlAttrPtr base;
00925 
00926        base = get_attribute(extType->properties, "base");
00927        if (base != NULL) {
00928               char *type, *ns;
00929               xmlNsPtr nsptr;
00930 
00931               parse_namespace(base->children->content, &type, &ns);
00932               nsptr = xmlSearchNs(extType->doc, extType, BAD_CAST(ns));
00933               if (nsptr != NULL) {
00934                      cur_type->encode = get_create_encoder(sdl, cur_type, nsptr->href, BAD_CAST(type));
00935               }
00936               if (type) {efree(type);}
00937               if (ns) {efree(ns);}
00938        } else {
00939               soap_error0(E_ERROR, "Parsing Schema: extension has no 'base' attribute");
00940        }
00941 
00942        trav = extType->children;
00943        if (trav != NULL && node_is_equal(trav,"annotation")) {
00944               /* TODO: <annotation> support */
00945               trav = trav->next;
00946        }
00947        if (trav != NULL) {
00948               if (node_is_equal(trav,"group")) {
00949                      schema_group(sdl, tns, trav, cur_type, NULL);
00950                      trav = trav->next;
00951               } else if (node_is_equal(trav,"all")) {
00952                      schema_all(sdl, tns, trav, cur_type, NULL);
00953                      trav = trav->next;
00954               } else if (node_is_equal(trav,"choice")) {
00955                      schema_choice(sdl, tns, trav, cur_type, NULL);
00956                      trav = trav->next;
00957               } else if (node_is_equal(trav,"sequence")) {
00958                      schema_sequence(sdl, tns, trav, cur_type, NULL);
00959                      trav = trav->next;
00960               }
00961        }
00962        while (trav != NULL) {
00963               if (node_is_equal(trav,"attribute")) {
00964                      schema_attribute(sdl, tns, trav, cur_type, NULL);
00965               } else if (node_is_equal(trav,"attributeGroup")) {
00966                      schema_attributeGroup(sdl, tns, trav, cur_type, NULL);
00967               } else if (node_is_equal(trav,"anyAttribute")) {
00968                      /* TODO: <anyAttribute> support */
00969                      trav = trav->next;
00970                      break;
00971               } else {
00972                      soap_error1(E_ERROR, "Parsing Schema: unexpected <%s> in extension", trav->name);
00973               }
00974               trav = trav->next;
00975        }
00976        if (trav != NULL) {
00977               soap_error1(E_ERROR, "Parsing Schema: unexpected <%s> in extension", trav->name);
00978        }
00979        return TRUE;
00980 }
00981 
00982 void schema_min_max(xmlNodePtr node, sdlContentModelPtr model)
00983 {
00984        xmlAttrPtr attr = get_attribute(node->properties, "minOccurs");
00985 
00986        if (attr) {
00987               model->min_occurs = atoi((char*)attr->children->content);
00988        } else {
00989               model->min_occurs = 1;
00990        }
00991 
00992        attr = get_attribute(node->properties, "maxOccurs");
00993        if (attr) {
00994               if (!strncmp((char*)attr->children->content, "unbounded", sizeof("unbounded"))) {
00995                      model->max_occurs = -1;
00996               } else {
00997                      model->max_occurs = atoi((char*)attr->children->content);
00998               }
00999        } else {
01000               model->max_occurs = 1;
01001        }
01002 }
01003 
01004 /*
01005 <all
01006   id = ID
01007   maxOccurs = 1 : 1
01008   minOccurs = (0 | 1) : 1
01009   {any attributes with non-schema namespace . . .}>
01010   Content: (annotation?, element*)
01011 </all>
01012 */
01013 static int schema_all(sdlPtr sdl, xmlAttrPtr tns, xmlNodePtr all, sdlTypePtr cur_type, sdlContentModelPtr model)
01014 {
01015        xmlNodePtr trav;
01016        sdlContentModelPtr newModel;
01017 
01018        newModel = emalloc(sizeof(sdlContentModel));
01019        newModel->kind = XSD_CONTENT_ALL;
01020        newModel->u.content = emalloc(sizeof(HashTable));
01021        zend_hash_init(newModel->u.content, 0, NULL, delete_model, 0);
01022        if (model == NULL) {
01023               cur_type->model = newModel;
01024        } else {
01025               zend_hash_next_index_insert(model->u.content,&newModel,sizeof(sdlContentModelPtr), NULL);
01026        }
01027 
01028        schema_min_max(all, newModel);
01029 
01030        trav = all->children;
01031        if (trav != NULL && node_is_equal(trav,"annotation")) {
01032               /* TODO: <annotation> support */
01033               trav = trav->next;
01034        }
01035        while (trav != NULL) {
01036               if (node_is_equal(trav,"element")) {
01037                      schema_element(sdl, tns, trav, cur_type, newModel);
01038               } else {
01039                      soap_error1(E_ERROR, "Parsing Schema: unexpected <%s> in all", trav->name);
01040               }
01041               trav = trav->next;
01042        }
01043        return TRUE;
01044 }
01045 
01046 /*
01047 <group
01048   name = NCName
01049   Content: (annotation?, (all | choice | sequence))
01050 </group>
01051 <group
01052   name = NCName
01053   ref = QName>
01054   Content: (annotation?)
01055 </group>
01056 */
01057 static int schema_group(sdlPtr sdl, xmlAttrPtr tns, xmlNodePtr groupType, sdlTypePtr cur_type, sdlContentModelPtr model)
01058 {
01059        xmlNodePtr trav;
01060        xmlAttrPtr ns, name, ref = NULL;
01061        sdlContentModelPtr newModel;
01062 
01063        ns = get_attribute(groupType->properties, "targetNamespace");
01064        if (ns == NULL) {
01065               ns = tns;
01066        }
01067 
01068        name = get_attribute(groupType->properties, "name");
01069        if (name == NULL) {
01070               name = ref = get_attribute(groupType->properties, "ref");
01071        }
01072 
01073        if (name) {
01074               smart_str key = {0};
01075 
01076               if (ref) {
01077                      char *type, *ns;
01078                      xmlNsPtr nsptr;
01079 
01080                      parse_namespace(ref->children->content, &type, &ns);
01081                      nsptr = xmlSearchNs(groupType->doc, groupType, BAD_CAST(ns));
01082                      if (nsptr != NULL) {
01083                             smart_str_appends(&key, (char*)nsptr->href);
01084                      }
01085                      smart_str_appendc(&key, ':');
01086                      smart_str_appends(&key, type);
01087                      smart_str_0(&key);
01088 
01089                      newModel = emalloc(sizeof(sdlContentModel));
01090                      newModel->kind = XSD_CONTENT_GROUP_REF;
01091                      newModel->u.group_ref = estrdup(key.c);
01092 
01093                      if (type) {efree(type);}
01094                      if (ns) {efree(ns);}
01095               } else {
01096                      newModel = emalloc(sizeof(sdlContentModel));
01097                      newModel->kind = XSD_CONTENT_SEQUENCE; /* will be redefined */
01098                      newModel->u.content = emalloc(sizeof(HashTable));
01099                      zend_hash_init(newModel->u.content, 0, NULL, delete_model, 0);
01100 
01101                      smart_str_appends(&key, (char*)ns->children->content);
01102                      smart_str_appendc(&key, ':');
01103                      smart_str_appends(&key, (char*)name->children->content);
01104                      smart_str_0(&key);
01105               }
01106 
01107               if (cur_type == NULL) {
01108                      sdlTypePtr newType;
01109 
01110                      newType = emalloc(sizeof(sdlType));
01111                      memset(newType, 0, sizeof(sdlType));
01112 
01113                      if (sdl->groups == NULL) {
01114                             sdl->groups = emalloc(sizeof(HashTable));
01115                             zend_hash_init(sdl->groups, 0, NULL, delete_type, 0);
01116                      }
01117                      if (zend_hash_add(sdl->groups, key.c, key.len+1, (void**)&newType, sizeof(sdlTypePtr), NULL) != SUCCESS) {
01118                             soap_error1(E_ERROR, "Parsing Schema: group '%s' already defined", key.c);
01119                      }
01120 
01121                      cur_type = newType;
01122               }
01123               smart_str_free(&key);
01124 
01125               if (model == NULL) {
01126                      cur_type->model = newModel;
01127               } else {
01128                      zend_hash_next_index_insert(model->u.content, &newModel, sizeof(sdlContentModelPtr), NULL);
01129               }
01130        } else {
01131               soap_error0(E_ERROR, "Parsing Schema: group has no 'name' nor 'ref' attributes");
01132        }
01133 
01134        schema_min_max(groupType, newModel);
01135 
01136        trav = groupType->children;
01137        if (trav != NULL && node_is_equal(trav,"annotation")) {
01138               /* TODO: <annotation> support */
01139               trav = trav->next;
01140        }
01141        if (trav != NULL) {
01142               if (node_is_equal(trav,"choice")) {
01143                      if (ref != NULL) {
01144                             soap_error0(E_ERROR, "Parsing Schema: group has both 'ref' attribute and subcontent");
01145                      }
01146                      newModel->kind = XSD_CONTENT_CHOICE;
01147                      schema_choice(sdl, tns, trav, cur_type, newModel);
01148                      trav = trav->next;
01149               } else if (node_is_equal(trav,"sequence")) {
01150                      if (ref != NULL) {
01151                             soap_error0(E_ERROR, "Parsing Schema: group has both 'ref' attribute and subcontent");
01152                      }
01153                      newModel->kind = XSD_CONTENT_SEQUENCE;
01154                      schema_sequence(sdl, tns, trav, cur_type, newModel);
01155                      trav = trav->next;
01156               } else if (node_is_equal(trav,"all")) {
01157                      if (ref != NULL) {
01158                             soap_error0(E_ERROR, "Parsing Schema: group has both 'ref' attribute and subcontent");
01159                      }
01160                      newModel->kind = XSD_CONTENT_ALL;
01161                      schema_all(sdl, tns, trav, cur_type, newModel);
01162                      trav = trav->next;
01163               } else {
01164                      soap_error1(E_ERROR, "Parsing Schema: unexpected <%s> in group", trav->name);
01165               }
01166        }
01167        if (trav != NULL) {
01168               soap_error1(E_ERROR, "Parsing Schema: unexpected <%s> in group", trav->name);
01169        }
01170        return TRUE;
01171 }
01172 /*
01173 <choice
01174   id = ID
01175   maxOccurs = (nonNegativeInteger | unbounded)  : 1
01176   minOccurs = nonNegativeInteger : 1
01177   {any attributes with non-schema namespace . . .}>
01178   Content: (annotation?, (element | group | choice | sequence | any)*)
01179 </choice>
01180 */
01181 static int schema_choice(sdlPtr sdl, xmlAttrPtr tns, xmlNodePtr choiceType, sdlTypePtr cur_type, sdlContentModelPtr model)
01182 {
01183        xmlNodePtr trav;
01184        sdlContentModelPtr newModel;
01185 
01186        newModel = emalloc(sizeof(sdlContentModel));
01187        newModel->kind = XSD_CONTENT_CHOICE;
01188        newModel->u.content = emalloc(sizeof(HashTable));
01189        zend_hash_init(newModel->u.content, 0, NULL, delete_model, 0);
01190        if (model == NULL) {
01191               cur_type->model = newModel;
01192        } else {
01193               zend_hash_next_index_insert(model->u.content,&newModel,sizeof(sdlContentModelPtr), NULL);
01194        }
01195 
01196        schema_min_max(choiceType, newModel);
01197 
01198        trav = choiceType->children;
01199        if (trav != NULL && node_is_equal(trav,"annotation")) {
01200               /* TODO: <annotation> support */
01201               trav = trav->next;
01202        }
01203        while (trav != NULL) {
01204               if (node_is_equal(trav,"element")) {
01205                      schema_element(sdl, tns, trav, cur_type, newModel);
01206               } else if (node_is_equal(trav,"group")) {
01207                      schema_group(sdl, tns, trav, cur_type, newModel);
01208               } else if (node_is_equal(trav,"choice")) {
01209                      schema_choice(sdl, tns, trav, cur_type, newModel);
01210               } else if (node_is_equal(trav,"sequence")) {
01211                      schema_sequence(sdl, tns, trav, cur_type, newModel);
01212               } else if (node_is_equal(trav,"any")) {
01213                      schema_any(sdl, tns, trav, cur_type, newModel);
01214               } else {
01215                      soap_error1(E_ERROR, "Parsing Schema: unexpected <%s> in choice", trav->name);
01216               }
01217               trav = trav->next;
01218        }
01219        return TRUE;
01220 }
01221 
01222 /*
01223 <sequence
01224   id = ID
01225   maxOccurs = (nonNegativeInteger | unbounded)  : 1
01226   minOccurs = nonNegativeInteger : 1
01227   {any attributes with non-schema namespace . . .}>
01228   Content: (annotation?, (element | group | choice | sequence | any)*)
01229 </sequence>
01230 */
01231 static int schema_sequence(sdlPtr sdl, xmlAttrPtr tns, xmlNodePtr seqType, sdlTypePtr cur_type, sdlContentModelPtr model)
01232 {
01233        xmlNodePtr trav;
01234        sdlContentModelPtr newModel;
01235 
01236        newModel = emalloc(sizeof(sdlContentModel));
01237        newModel->kind = XSD_CONTENT_SEQUENCE;
01238        newModel->u.content = emalloc(sizeof(HashTable));
01239        zend_hash_init(newModel->u.content, 0, NULL, delete_model, 0);
01240        if (model == NULL) {
01241               cur_type->model = newModel;
01242        } else {
01243               zend_hash_next_index_insert(model->u.content,&newModel,sizeof(sdlContentModelPtr), NULL);
01244        }
01245 
01246        schema_min_max(seqType, newModel);
01247 
01248        trav = seqType->children;
01249        if (trav != NULL && node_is_equal(trav,"annotation")) {
01250               /* TODO: <annotation> support */
01251               trav = trav->next;
01252        }
01253        while (trav != NULL) {
01254               if (node_is_equal(trav,"element")) {
01255                      schema_element(sdl, tns, trav, cur_type, newModel);
01256               } else if (node_is_equal(trav,"group")) {
01257                      schema_group(sdl, tns, trav, cur_type, newModel);
01258               } else if (node_is_equal(trav,"choice")) {
01259                      schema_choice(sdl, tns, trav, cur_type, newModel);
01260               } else if (node_is_equal(trav,"sequence")) {
01261                      schema_sequence(sdl, tns, trav, cur_type, newModel);
01262               } else if (node_is_equal(trav,"any")) {
01263                      schema_any(sdl, tns, trav, cur_type, newModel);
01264               } else {
01265                      soap_error1(E_ERROR, "Parsing Schema: unexpected <%s> in sequence", trav->name);
01266               }
01267               trav = trav->next;
01268        }
01269        return TRUE;
01270 }
01271 
01272 /*
01273 <any 
01274   id = ID 
01275   maxOccurs = (nonNegativeInteger | unbounded)  : 1
01276   minOccurs = nonNegativeInteger : 1
01277   namespace = ((##any | ##other) | List of (anyURI | (##targetNamespace | ##local)) )  : ##any
01278   processContents = (lax | skip | strict) : strict
01279   {any attributes with non-schema namespace . . .}>
01280   Content: (annotation?)
01281 </any>
01282 */
01283 static int schema_any(sdlPtr sdl, xmlAttrPtr tns, xmlNodePtr anyType, sdlTypePtr cur_type, sdlContentModelPtr model)
01284 {
01285        if (model != NULL) {
01286               sdlContentModelPtr newModel;
01287 
01288               newModel = emalloc(sizeof(sdlContentModel));
01289               newModel->kind = XSD_CONTENT_ANY;
01290 
01291               schema_min_max(anyType, newModel);
01292 
01293               zend_hash_next_index_insert(model->u.content, &newModel, sizeof(sdlContentModelPtr), NULL);
01294        }
01295        return TRUE;
01296 }
01297 
01298 /*
01299 <complexContent
01300   id = ID
01301   mixed = boolean
01302   {any attributes with non-schema namespace . . .}>
01303   Content: (annotation?, (restriction | extension))
01304 </complexContent>
01305 */
01306 static int schema_complexContent(sdlPtr sdl, xmlAttrPtr tns, xmlNodePtr compCont, sdlTypePtr cur_type)
01307 {
01308        xmlNodePtr trav;
01309 
01310        trav = compCont->children;
01311        if (trav != NULL && node_is_equal(trav,"annotation")) {
01312               /* TODO: <annotation> support */
01313               trav = trav->next;
01314        }
01315        if (trav != NULL) {
01316               if (node_is_equal(trav, "restriction")) {
01317                      cur_type->kind = XSD_TYPEKIND_RESTRICTION;
01318                      schema_restriction_complexContent(sdl, tns, trav, cur_type);
01319                      trav = trav->next;
01320               } else if (node_is_equal(trav, "extension")) {
01321                      cur_type->kind = XSD_TYPEKIND_EXTENSION;
01322                      schema_extension_complexContent(sdl, tns, trav, cur_type);
01323                      trav = trav->next;
01324               } else {
01325                      soap_error1(E_ERROR, "Parsing Schema: unexpected <%s> in complexContent", trav->name);
01326               }
01327        } else {
01328               soap_error0(E_ERROR, "Parsing Schema: <restriction> or <extension> expected in complexContent");
01329        }
01330        if (trav != NULL) {
01331               soap_error1(E_ERROR, "Parsing Schema: unexpected <%s> in complexContent", trav->name);
01332        }
01333 
01334        return TRUE;
01335 }
01336 
01337 /*
01338 <complexType
01339   abstract = boolean : false
01340   block = (#all | List of (extension | restriction))
01341   final = (#all | List of (extension | restriction))
01342   id = ID
01343   mixed = boolean : false
01344   name = NCName
01345   {any attributes with non-schema namespace . . .}>
01346   Content: (annotation?, (simpleContent | complexContent | ((group | all | choice | sequence)?, ((attribute | attributeGroup)*, anyAttribute?))))
01347 </complexType>
01348 */
01349 static int schema_complexType(sdlPtr sdl, xmlAttrPtr tns, xmlNodePtr compType, sdlTypePtr cur_type)
01350 {
01351        xmlNodePtr trav;
01352        xmlAttrPtr attrs, name, ns;
01353 
01354        attrs = compType->properties;
01355        ns = get_attribute(attrs, "targetNamespace");
01356        if (ns == NULL) {
01357               ns = tns;
01358        }
01359 
01360        name = get_attribute(attrs, "name");
01361        if (cur_type != NULL) {
01362               /* Anonymous type inside <element> */
01363               sdlTypePtr newType, *ptr;
01364 
01365               newType = emalloc(sizeof(sdlType));
01366               memset(newType, 0, sizeof(sdlType));
01367               newType->kind = XSD_TYPEKIND_COMPLEX;
01368               if (name != NULL) {
01369                      newType->name = estrdup((char*)name->children->content);
01370                      newType->namens = estrdup((char*)ns->children->content);
01371               } else {
01372                      newType->name = estrdup(cur_type->name);
01373                      newType->namens = estrdup(cur_type->namens);
01374               }
01375 
01376               zend_hash_next_index_insert(sdl->types,  &newType, sizeof(sdlTypePtr), (void **)&ptr);
01377 
01378               if (sdl->encoders == NULL) {
01379                      sdl->encoders = emalloc(sizeof(HashTable));
01380                      zend_hash_init(sdl->encoders, 0, NULL, delete_encoder, 0);
01381               }
01382               cur_type->encode = emalloc(sizeof(encode));
01383               memset(cur_type->encode, 0, sizeof(encode));
01384               cur_type->encode->details.ns = estrdup(newType->namens);
01385               cur_type->encode->details.type_str = estrdup(newType->name);
01386               cur_type->encode->details.sdl_type = *ptr;
01387               cur_type->encode->to_xml = sdl_guess_convert_xml;
01388               cur_type->encode->to_zval = sdl_guess_convert_zval;
01389               zend_hash_next_index_insert(sdl->encoders,  &cur_type->encode, sizeof(encodePtr), NULL);
01390 
01391               cur_type =*ptr;
01392 
01393        } else if (name) {
01394               sdlTypePtr newType, *ptr;
01395 
01396               newType = emalloc(sizeof(sdlType));
01397               memset(newType, 0, sizeof(sdlType));
01398               newType->kind = XSD_TYPEKIND_COMPLEX;
01399               newType->name = estrdup((char*)name->children->content);
01400               newType->namens = estrdup((char*)ns->children->content);
01401 
01402               zend_hash_next_index_insert(sdl->types,  &newType, sizeof(sdlTypePtr), (void **)&ptr);
01403 
01404               cur_type = (*ptr);
01405               create_encoder(sdl, cur_type, ns->children->content, name->children->content);
01406        } else {
01407               soap_error0(E_ERROR, "Parsing Schema: complexType has no 'name' attribute");
01408               return FALSE;
01409        }
01410 
01411        trav = compType->children;
01412        if (trav != NULL && node_is_equal(trav, "annotation")) {
01413               /* TODO: <annotation> support */
01414               trav = trav->next;
01415        }
01416        if (trav != NULL) {
01417               if (node_is_equal(trav,"simpleContent")) {
01418                      schema_simpleContent(sdl, tns, trav, cur_type);
01419                      trav = trav->next;
01420               } else if (node_is_equal(trav,"complexContent")) {
01421                      schema_complexContent(sdl, tns, trav, cur_type);
01422                      trav = trav->next;
01423               } else {
01424                      if (node_is_equal(trav,"group")) {
01425                             schema_group(sdl, tns, trav, cur_type, NULL);
01426                             trav = trav->next;
01427                      } else if (node_is_equal(trav,"all")) {
01428                             schema_all(sdl, tns, trav, cur_type, NULL);
01429                             trav = trav->next;
01430                      } else if (node_is_equal(trav,"choice")) {
01431                             schema_choice(sdl, tns, trav, cur_type, NULL);
01432                             trav = trav->next;
01433                      } else if (node_is_equal(trav,"sequence")) {
01434                             schema_sequence(sdl, tns, trav, cur_type, NULL);
01435                             trav = trav->next;
01436                      }
01437                      while (trav != NULL) {
01438                             if (node_is_equal(trav,"attribute")) {
01439                                    schema_attribute(sdl, tns, trav, cur_type, NULL);
01440                             } else if (node_is_equal(trav,"attributeGroup")) {
01441                                    schema_attributeGroup(sdl, tns, trav, cur_type, NULL);
01442                             } else if (node_is_equal(trav,"anyAttribute")) {
01443                                    /* TODO: <anyAttribute> support */
01444                                    trav = trav->next;
01445                                    break;
01446                             } else {
01447                                    soap_error1(E_ERROR, "Parsing Schema: unexpected <%s> in complexType", trav->name);
01448                             }
01449                             trav = trav->next;
01450                      }
01451               }
01452        }
01453        if (trav != NULL) {
01454               soap_error1(E_ERROR, "Parsing Schema: unexpected <%s> in complexType", trav->name);
01455        }
01456        return TRUE;
01457 }
01458 /*
01459 <element
01460   abstract = boolean : false
01461   block = (#all | List of (extension | restriction | substitution))
01462   default = string
01463   final = (#all | List of (extension | restriction))
01464   fixed = string
01465   form = (qualified | unqualified)
01466   id = ID
01467   maxOccurs = (nonNegativeInteger | unbounded)  : 1
01468   minOccurs = nonNegativeInteger : 1
01469   name = NCName
01470   nillable = boolean : false
01471   ref = QName
01472   substitutionGroup = QName
01473   type = QName
01474   {any attributes with non-schema namespace . . .}>
01475   Content: (annotation?, ((simpleType | complexType)?, (unique | key | keyref)*))
01476 </element>
01477 */
01478 static int schema_element(sdlPtr sdl, xmlAttrPtr tns, xmlNodePtr element, sdlTypePtr cur_type, sdlContentModelPtr model)
01479 {
01480        xmlNodePtr trav;
01481        xmlAttrPtr attrs, attr, ns, name, type, ref = NULL;
01482 
01483        attrs = element->properties;
01484        ns = get_attribute(attrs, "targetNamespace");
01485        if (ns == NULL) {
01486               ns = tns;
01487        }
01488 
01489        name = get_attribute(attrs, "name");
01490        if (name == NULL) {
01491               name = ref = get_attribute(attrs, "ref");
01492        }
01493 
01494        if (name) {
01495               HashTable *addHash;
01496               sdlTypePtr newType;
01497               smart_str key = {0};
01498 
01499               newType = emalloc(sizeof(sdlType));
01500               memset(newType, 0, sizeof(sdlType));
01501 
01502               if (ref) {
01503                      smart_str nscat = {0};
01504                      char *type, *ns;
01505                      xmlNsPtr nsptr;
01506 
01507                      parse_namespace(ref->children->content, &type, &ns);
01508                      nsptr = xmlSearchNs(element->doc, element, BAD_CAST(ns));
01509                      if (nsptr != NULL) {
01510                             smart_str_appends(&nscat, (char*)nsptr->href);
01511                             newType->namens = estrdup((char*)nsptr->href);
01512                      } 
01513                      smart_str_appendc(&nscat, ':');
01514                      smart_str_appends(&nscat, type);
01515                      newType->name = estrdup(type);
01516                      smart_str_0(&nscat);
01517                      if (type) {efree(type);}
01518                      if (ns) {efree(ns);}
01519                      newType->ref = estrdup(nscat.c);
01520                      smart_str_free(&nscat);
01521               } else {
01522                      newType->name = estrdup((char*)name->children->content);
01523                      newType->namens = estrdup((char*)ns->children->content);
01524               }
01525 
01526               newType->nillable = FALSE;
01527 
01528               if (cur_type == NULL) {
01529                      if (sdl->elements == NULL) {
01530                             sdl->elements = emalloc(sizeof(HashTable));
01531                             zend_hash_init(sdl->elements, 0, NULL, delete_type, 0);
01532                      }
01533                      addHash = sdl->elements;
01534                      smart_str_appends(&key, newType->namens);
01535                      smart_str_appendc(&key, ':');
01536                      smart_str_appends(&key, newType->name);
01537               } else {
01538                      if (cur_type->elements == NULL) {
01539                             cur_type->elements = emalloc(sizeof(HashTable));
01540                             zend_hash_init(cur_type->elements, 0, NULL, delete_type, 0);
01541                      }
01542                      addHash = cur_type->elements;
01543                      smart_str_appends(&key, newType->name);
01544               }
01545 
01546               smart_str_0(&key);
01547               if (zend_hash_add(addHash, key.c, key.len + 1, &newType, sizeof(sdlTypePtr), NULL) != SUCCESS) {
01548                      if (cur_type == NULL) {
01549                             soap_error1(E_ERROR, "Parsing Schema: element '%s' already defined", key.c);
01550                      } else {
01551                             zend_hash_next_index_insert(addHash, &newType, sizeof(sdlTypePtr), NULL);
01552                      }
01553               }
01554               smart_str_free(&key);
01555 
01556               if (model != NULL) {
01557                      sdlContentModelPtr newModel = emalloc(sizeof(sdlContentModel));
01558 
01559                      newModel->kind = XSD_CONTENT_ELEMENT;
01560                      newModel->u.element = newType;
01561 
01562                      schema_min_max(element, newModel);
01563 
01564 
01565                      zend_hash_next_index_insert(model->u.content, &newModel, sizeof(sdlContentModelPtr), NULL);
01566               }
01567               cur_type = newType;
01568        } else {
01569               soap_error0(E_ERROR, "Parsing Schema: element has no 'name' nor 'ref' attributes");
01570        }
01571 
01572        /* nillable = boolean : false */
01573        attrs = element->properties;
01574        attr = get_attribute(attrs, "nillable");
01575        if (attr) {
01576               if (ref != NULL) {
01577                      soap_error0(E_ERROR, "Parsing Schema: element has both 'ref' and 'nillable' attributes");
01578               }
01579               if (!stricmp((char*)attr->children->content, "true") ||
01580                      !stricmp((char*)attr->children->content, "1")) {
01581                      cur_type->nillable = TRUE;
01582               } else {
01583                      cur_type->nillable = FALSE;
01584               }
01585        } else {
01586               cur_type->nillable = FALSE;
01587        }
01588 
01589        attr = get_attribute(attrs, "fixed");
01590        if (attr) {
01591               if (ref != NULL) {
01592                      soap_error0(E_ERROR, "Parsing Schema: element has both 'ref' and 'fixed' attributes");
01593               }
01594               cur_type->fixed = estrdup((char*)attr->children->content);
01595        }
01596 
01597        attr = get_attribute(attrs, "default");
01598        if (attr) {
01599               if (ref != NULL) {
01600                      soap_error0(E_ERROR, "Parsing Schema: element has both 'ref' and 'fixed' attributes");
01601               } else if (ref != NULL) {
01602                      soap_error0(E_ERROR, "Parsing Schema: element has both 'default' and 'fixed' attributes");
01603               }
01604               cur_type->def = estrdup((char*)attr->children->content);
01605        }
01606 
01607        /* form */
01608        attr = get_attribute(attrs, "form");
01609        if (attr) {
01610               if (strncmp((char*)attr->children->content, "qualified", sizeof("qualified")) == 0) {
01611                 cur_type->form = XSD_FORM_QUALIFIED;
01612               } else if (strncmp((char*)attr->children->content, "unqualified", sizeof("unqualified")) == 0) {
01613                 cur_type->form = XSD_FORM_UNQUALIFIED;
01614               } else {
01615                 cur_type->form = XSD_FORM_DEFAULT;
01616               }
01617        } else {
01618          cur_type->form = XSD_FORM_DEFAULT;
01619        }
01620        if (cur_type->form == XSD_FORM_DEFAULT) {
01621               xmlNodePtr parent = element->parent;
01622               while (parent) {
01623                      if (node_is_equal_ex(parent, "schema", SCHEMA_NAMESPACE)) {
01624                             xmlAttrPtr def;
01625                             def = get_attribute(parent->properties, "elementFormDefault");
01626                             if(def == NULL || strncmp((char*)def->children->content, "qualified", sizeof("qualified"))) {
01627                                    cur_type->form = XSD_FORM_UNQUALIFIED;
01628                             } else {
01629                                    cur_type->form = XSD_FORM_QUALIFIED;
01630                             }
01631                             break;
01632                      }
01633                      parent = parent->parent;
01634        }
01635               if (parent == NULL) {
01636                      cur_type->form = XSD_FORM_UNQUALIFIED;
01637               }      
01638        }
01639 
01640        /* type = QName */
01641        type = get_attribute(attrs, "type");
01642        if (type) {
01643               char *cptype, *str_ns;
01644               xmlNsPtr nsptr;
01645 
01646               if (ref != NULL) {
01647                      soap_error0(E_ERROR, "Parsing Schema: element has both 'ref' and 'type' attributes");
01648               }
01649               parse_namespace(type->children->content, &cptype, &str_ns);
01650               nsptr = xmlSearchNs(element->doc, element, BAD_CAST(str_ns));
01651               if (nsptr != NULL) {
01652                      cur_type->encode = get_create_encoder(sdl, cur_type, nsptr->href, BAD_CAST(cptype));
01653               }
01654               if (str_ns) {efree(str_ns);}
01655               if (cptype) {efree(cptype);}
01656        }
01657 
01658        trav = element->children;
01659        if (trav != NULL && node_is_equal(trav, "annotation")) {
01660               /* TODO: <annotation> support */
01661               trav = trav->next;
01662        }
01663        if (trav != NULL) {
01664               if (node_is_equal(trav,"simpleType")) {
01665                      if (ref != NULL) {
01666                             soap_error0(E_ERROR, "Parsing Schema: element has both 'ref' attribute and subtype");
01667                      } else if (type != NULL) {
01668                             soap_error0(E_ERROR, "Parsing Schema: element has both 'type' attribute and subtype");
01669                      }
01670                      schema_simpleType(sdl, tns, trav, cur_type);
01671                      trav = trav->next;
01672               } else if (node_is_equal(trav,"complexType")) {
01673                      if (ref != NULL) {
01674                             soap_error0(E_ERROR, "Parsing Schema: element has both 'ref' attribute and subtype");
01675                      } else if (type != NULL) {
01676                             soap_error0(E_ERROR, "Parsing Schema: element has both 'type' attribute and subtype");
01677                      }
01678                      schema_complexType(sdl, tns, trav, cur_type);
01679                      trav = trav->next;
01680               }
01681        }
01682        while (trav != NULL) {
01683               if (node_is_equal(trav,"unique")) {
01684                      /* TODO: <unique> support */
01685               } else if (node_is_equal(trav,"key")) {
01686                      /* TODO: <key> support */
01687               } else if (node_is_equal(trav,"keyref")) {
01688                      /* TODO: <keyref> support */
01689               } else {
01690                      soap_error1(E_ERROR, "Parsing Schema: unexpected <%s> in element", trav->name);
01691               }
01692               trav = trav->next;
01693        }
01694 
01695        return TRUE;
01696 }
01697 
01698 /*
01699 <attribute
01700   default = string
01701   fixed = string
01702   form = (qualified | unqualified)
01703   id = ID
01704   name = NCName
01705   ref = QName
01706   type = QName
01707   use = (optional | prohibited | required) : optional
01708   {any attributes with non-schema namespace . . .}>
01709   Content: (annotation?, (simpleType?))
01710 </attribute>
01711 */
01712 static int schema_attribute(sdlPtr sdl, xmlAttrPtr tns, xmlNodePtr attrType, sdlTypePtr cur_type, sdlCtx *ctx)
01713 {
01714        sdlAttributePtr newAttr;
01715        xmlAttrPtr attr, name, ref = NULL, type = NULL;
01716        xmlNodePtr trav;
01717 
01718        name = get_attribute(attrType->properties, "name");
01719        if (name == NULL) {
01720               name = ref = get_attribute(attrType->properties, "ref");
01721        }
01722        if (name) {
01723               HashTable *addHash;
01724               smart_str key = {0};
01725 
01726               newAttr = emalloc(sizeof(sdlAttribute));
01727               memset(newAttr, 0, sizeof(sdlAttribute));
01728 
01729               if (ref) {
01730                      char *attr_name, *ns;
01731                      xmlNsPtr nsptr;
01732 
01733                      parse_namespace(ref->children->content, &attr_name, &ns);
01734                      nsptr = xmlSearchNs(attrType->doc, attrType, BAD_CAST(ns));
01735                      if (nsptr != NULL) {
01736                             smart_str_appends(&key, (char*)nsptr->href);
01737                             newAttr->namens = estrdup((char*)nsptr->href);
01738                      }
01739                      smart_str_appendc(&key, ':');
01740                      smart_str_appends(&key, attr_name);
01741                      smart_str_0(&key);
01742                      newAttr->ref = estrdup(key.c);
01743                      if (attr_name) {efree(attr_name);}
01744                      if (ns) {efree(ns);}
01745               } else {
01746                      xmlAttrPtr ns;
01747 
01748                      ns = get_attribute(attrType->properties, "targetNamespace");
01749                      if (ns == NULL) {
01750                             ns = tns;
01751                      }
01752                      if (ns != NULL) {
01753                             smart_str_appends(&key, (char*)ns->children->content);
01754                             smart_str_appendc(&key, ':');
01755                             newAttr->namens = estrdup((char*)ns->children->content);
01756                      }
01757                      smart_str_appends(&key, (char*)name->children->content);
01758                      smart_str_0(&key);
01759               }
01760 
01761               if (cur_type == NULL) {
01762                      addHash = ctx->attributes;
01763               } else {
01764                      if (cur_type->attributes == NULL) {
01765                             cur_type->attributes = emalloc(sizeof(HashTable));
01766                             zend_hash_init(cur_type->attributes, 0, NULL, delete_attribute, 0);
01767                      }
01768                      addHash = cur_type->attributes;
01769               }
01770 
01771               if (zend_hash_add(addHash, key.c, key.len + 1, &newAttr, sizeof(sdlAttributePtr), NULL) != SUCCESS) {
01772                      soap_error1(E_ERROR, "Parsing Schema: attribute '%s' already defined", key.c);
01773               }
01774               smart_str_free(&key);
01775        } else{
01776               soap_error0(E_ERROR, "Parsing Schema: attribute has no 'name' nor 'ref' attributes");
01777        }
01778 
01779        /* type = QName */
01780        type = get_attribute(attrType->properties, "type");
01781        if (type) {
01782               char *cptype, *str_ns;
01783               xmlNsPtr nsptr;
01784 
01785               if (ref != NULL) {
01786                      soap_error0(E_ERROR, "Parsing Schema: attribute has both 'ref' and 'type' attributes");
01787               }
01788               parse_namespace(type->children->content, &cptype, &str_ns);
01789               nsptr = xmlSearchNs(attrType->doc, attrType, BAD_CAST(str_ns));
01790               if (nsptr != NULL) {
01791                      newAttr->encode = get_create_encoder(sdl, cur_type, nsptr->href, BAD_CAST(cptype));
01792               }
01793               if (str_ns) {efree(str_ns);}
01794               if (cptype) {efree(cptype);}
01795        }
01796 
01797        attr = attrType->properties;
01798        while (attr != NULL) {
01799               if (attr_is_equal_ex(attr, "default", SCHEMA_NAMESPACE)) {
01800                      newAttr->def = estrdup((char*)attr->children->content);
01801               } else if (attr_is_equal_ex(attr, "fixed", SCHEMA_NAMESPACE)) {
01802                      newAttr->fixed = estrdup((char*)attr->children->content);
01803               } else if (attr_is_equal_ex(attr, "form", SCHEMA_NAMESPACE)) {
01804                      if (strncmp((char*)attr->children->content, "qualified", sizeof("qualified")) == 0) {
01805                        newAttr->form = XSD_FORM_QUALIFIED;
01806                      } else if (strncmp((char*)attr->children->content, "unqualified", sizeof("unqualified")) == 0) {
01807                        newAttr->form = XSD_FORM_UNQUALIFIED;
01808                      } else {
01809                        newAttr->form = XSD_FORM_DEFAULT;
01810                      }
01811               } else if (attr_is_equal_ex(attr, "id", SCHEMA_NAMESPACE)) {
01812                      /* skip */
01813               } else if (attr_is_equal_ex(attr, "name", SCHEMA_NAMESPACE)) {
01814                      newAttr->name = estrdup((char*)attr->children->content);
01815               } else if (attr_is_equal_ex(attr, "ref", SCHEMA_NAMESPACE)) {
01816                      /* already processed */
01817               } else if (attr_is_equal_ex(attr, "type", SCHEMA_NAMESPACE)) {
01818                      /* already processed */
01819               } else if (attr_is_equal_ex(attr, "use", SCHEMA_NAMESPACE)) {
01820                      if (strncmp((char*)attr->children->content, "prohibited", sizeof("prohibited")) == 0) {
01821                        newAttr->use = XSD_USE_PROHIBITED;
01822                      } else if (strncmp((char*)attr->children->content, "required", sizeof("required")) == 0) {
01823                        newAttr->use = XSD_USE_REQUIRED;
01824                      } else if (strncmp((char*)attr->children->content, "optional", sizeof("optional")) == 0) {
01825                        newAttr->use = XSD_USE_OPTIONAL;
01826                      } else {
01827                        newAttr->use = XSD_USE_DEFAULT;
01828                      }
01829               } else {
01830                      xmlNsPtr nsPtr = attr_find_ns(attr);
01831 
01832                      if (strncmp((char*)nsPtr->href, SCHEMA_NAMESPACE, sizeof(SCHEMA_NAMESPACE))) {
01833                             smart_str key2 = {0};
01834                             sdlExtraAttributePtr ext;
01835                             xmlNsPtr nsptr;
01836                             char *value, *ns;
01837 
01838                             ext = emalloc(sizeof(sdlExtraAttribute));
01839                             memset(ext, 0, sizeof(sdlExtraAttribute));
01840                             parse_namespace(attr->children->content, &value, &ns);
01841                             nsptr = xmlSearchNs(attr->doc, attr->parent, BAD_CAST(ns));
01842                             if (nsptr) {
01843                                    ext->ns = estrdup((char*)nsptr->href);
01844                                    ext->val = estrdup(value);
01845                             } else {
01846                                    ext->val = estrdup((char*)attr->children->content);
01847                             }
01848                             if (ns) {efree(ns);}
01849                             efree(value);
01850 
01851                             if (!newAttr->extraAttributes) {
01852                                    newAttr->extraAttributes = emalloc(sizeof(HashTable));
01853                                    zend_hash_init(newAttr->extraAttributes, 0, NULL, delete_extra_attribute, 0);
01854                             }
01855 
01856                             smart_str_appends(&key2, (char*)nsPtr->href);
01857                             smart_str_appendc(&key2, ':');
01858                             smart_str_appends(&key2, (char*)attr->name);
01859                             smart_str_0(&key2);
01860                             zend_hash_add(newAttr->extraAttributes, key2.c, key2.len + 1, &ext, sizeof(sdlExtraAttributePtr), NULL);
01861                             smart_str_free(&key2);
01862                      }
01863               }
01864               attr = attr->next;
01865        }
01866        if (newAttr->form == XSD_FORM_DEFAULT) {
01867               xmlNodePtr parent = attrType->parent;
01868               while (parent) {
01869                      if (node_is_equal_ex(parent, "schema", SCHEMA_NAMESPACE)) {
01870                             xmlAttrPtr def;
01871                             def = get_attribute(parent->properties, "attributeFormDefault");
01872                             if(def == NULL || strncmp((char*)def->children->content, "qualified", sizeof("qualified"))) {
01873                                    newAttr->form = XSD_FORM_UNQUALIFIED;
01874                             } else {
01875                                    newAttr->form = XSD_FORM_QUALIFIED;
01876                             }
01877                             break;
01878                      }
01879                      parent = parent->parent;
01880        }
01881               if (parent == NULL) {
01882                      newAttr->form = XSD_FORM_UNQUALIFIED;
01883               }      
01884        }
01885        trav = attrType->children;
01886        if (trav != NULL && node_is_equal(trav, "annotation")) {
01887               /* TODO: <annotation> support */
01888               trav = trav->next;
01889        }
01890        if (trav != NULL) {
01891               if (node_is_equal(trav,"simpleType")) {
01892                      sdlTypePtr dummy_type;
01893                      if (ref != NULL) {
01894                             soap_error0(E_ERROR, "Parsing Schema: attribute has both 'ref' attribute and subtype");
01895                      } else if (type != NULL) {
01896                             soap_error0(E_ERROR, "Parsing Schema: attribute has both 'type' attribute and subtype");
01897                      }
01898                      dummy_type = emalloc(sizeof(sdlType));
01899                      memset(dummy_type, 0, sizeof(sdlType));
01900                      {
01901                             smart_str anonymous = {0};
01902                      
01903                             smart_str_appendl(&anonymous, "anonymous", sizeof("anonymous")-1);
01904                             smart_str_append_long(&anonymous, zend_hash_num_elements(sdl->types));
01905                             smart_str_0(&anonymous);
01906                             dummy_type->name = anonymous.c;
01907                      }
01908                      dummy_type->namens = estrdup((char*)tns->children->content);
01909                      schema_simpleType(sdl, tns, trav, dummy_type);
01910                      newAttr->encode = dummy_type->encode;
01911                      delete_type(&dummy_type);
01912                      trav = trav->next;
01913               }
01914        }
01915        if (trav != NULL) {
01916               soap_error1(E_ERROR, "Parsing Schema: unexpected <%s> in attribute", trav->name);
01917        }
01918        return TRUE;
01919 }
01920 
01921 static int schema_attributeGroup(sdlPtr sdl, xmlAttrPtr tns, xmlNodePtr attrGroup, sdlTypePtr cur_type, sdlCtx *ctx)
01922 {
01923        xmlNodePtr trav;
01924        xmlAttrPtr name, ref = NULL;
01925 
01926 
01927        name = get_attribute(attrGroup->properties, "name");
01928        if (name == NULL) {
01929               name = ref = get_attribute(attrGroup->properties, "ref");
01930        }
01931        if (name) {
01932               if (cur_type == NULL) {
01933                      xmlAttrPtr ns;
01934                      sdlTypePtr newType;
01935                      smart_str key = {0};
01936 
01937                      ns = get_attribute(attrGroup->properties, "targetNamespace");
01938                      if (ns == NULL) {
01939                             ns = tns;
01940                      }
01941                      newType = emalloc(sizeof(sdlType));
01942                      memset(newType, 0, sizeof(sdlType));
01943                      newType->name = estrdup((char*)name->children->content);
01944                      newType->namens = estrdup((char*)ns->children->content);
01945 
01946                      smart_str_appends(&key, newType->namens);
01947                      smart_str_appendc(&key, ':');
01948                      smart_str_appends(&key, newType->name);
01949                      smart_str_0(&key);
01950 
01951                      if (zend_hash_add(ctx->attributeGroups, key.c, key.len + 1, &newType, sizeof(sdlTypePtr), NULL) != SUCCESS) {
01952                             soap_error1(E_ERROR, "Parsing Schema: attributeGroup '%s' already defined", key.c);
01953                      }
01954                      cur_type = newType;
01955                      smart_str_free(&key);
01956               } else if (ref) {
01957                      sdlAttributePtr newAttr;
01958                      char *group_name, *ns;
01959                      smart_str key = {0};
01960                      xmlNsPtr nsptr;
01961 
01962                      if (cur_type->attributes == NULL) {
01963                             cur_type->attributes = emalloc(sizeof(HashTable));
01964                             zend_hash_init(cur_type->attributes, 0, NULL, delete_attribute, 0);
01965                      }
01966                      newAttr = emalloc(sizeof(sdlAttribute));
01967                      memset(newAttr, 0, sizeof(sdlAttribute));
01968 
01969                      parse_namespace(ref->children->content, &group_name, &ns);
01970                      nsptr = xmlSearchNs(attrGroup->doc, attrGroup, BAD_CAST(ns));
01971                      if (nsptr != NULL) {
01972                             smart_str_appends(&key, (char*)nsptr->href);
01973                      }
01974                      smart_str_appendc(&key, ':');
01975                      smart_str_appends(&key, group_name);
01976                      smart_str_0(&key);
01977                      newAttr->ref = estrdup(key.c);
01978                      if (group_name) {efree(group_name);}
01979                      if (ns) {efree(ns);}
01980                      smart_str_free(&key);
01981 
01982                      zend_hash_next_index_insert(cur_type->attributes, &newAttr, sizeof(sdlAttributePtr), NULL);
01983                      cur_type = NULL;
01984               }
01985        } else{
01986               soap_error0(E_ERROR, "Parsing Schema: attributeGroup has no 'name' nor 'ref' attributes");
01987        }
01988 
01989        trav = attrGroup->children;
01990        if (trav != NULL && node_is_equal(trav, "annotation")) {
01991               /* TODO: <annotation> support */
01992               trav = trav->next;
01993        }
01994        while (trav != NULL) {
01995               if (node_is_equal(trav,"attribute")) {
01996                      if (ref != NULL) {
01997                             soap_error0(E_ERROR, "Parsing Schema: attributeGroup has both 'ref' attribute and subattribute");
01998                      }
01999                      schema_attribute(sdl, tns, trav, cur_type, NULL);
02000               } else if (node_is_equal(trav,"attributeGroup")) {
02001                      if (ref != NULL) {
02002                             soap_error0(E_ERROR, "Parsing Schema: attributeGroup has both 'ref' attribute and subattribute");
02003                      }
02004                      schema_attributeGroup(sdl, tns, trav, cur_type, NULL);
02005               } else if (node_is_equal(trav,"anyAttribute")) {
02006                      if (ref != NULL) {
02007                             soap_error0(E_ERROR, "Parsing Schema: attributeGroup has both 'ref' attribute and subattribute");
02008                      }
02009                      /* TODO: <anyAttribute> support */
02010                      trav = trav->next;
02011                      break;
02012               } else {
02013                      soap_error1(E_ERROR, "Parsing Schema: unexpected <%s> in attributeGroup", trav->name);
02014               }
02015               trav = trav->next;
02016        }
02017        if (trav != NULL) {
02018               soap_error1(E_ERROR, "Parsing Schema: unexpected <%s> in attributeGroup", trav->name);
02019        }
02020        return TRUE;
02021 }
02022 
02023 static void copy_extra_attribute(void *attribute)
02024 {
02025        sdlExtraAttributePtr *attr = (sdlExtraAttributePtr*)attribute;
02026        sdlExtraAttributePtr new_attr;
02027 
02028        new_attr = emalloc(sizeof(sdlExtraAttribute));
02029        memcpy(new_attr, *attr, sizeof(sdlExtraAttribute));
02030        *attr = new_attr;
02031        if (new_attr->ns) {
02032               new_attr->ns = estrdup(new_attr->ns);
02033        }
02034        if (new_attr->val) {
02035               new_attr->val = estrdup(new_attr->val);
02036        }
02037 }
02038 
02039 static void schema_attribute_fixup(sdlCtx *ctx, sdlAttributePtr attr)
02040 {
02041        sdlAttributePtr *tmp;
02042 
02043        if (attr->ref != NULL) {
02044               if (ctx->attributes != NULL) {
02045                      if (zend_hash_find(ctx->attributes, attr->ref, strlen(attr->ref)+1, (void**)&tmp) == SUCCESS) {
02046                             schema_attribute_fixup(ctx, *tmp);
02047                             if ((*tmp)->name != NULL && attr->name == NULL) {
02048                                    attr->name = estrdup((*tmp)->name);
02049                             }
02050                             if ((*tmp)->namens != NULL && attr->namens == NULL) {
02051                                    attr->namens = estrdup((*tmp)->namens);
02052                             }
02053                             if ((*tmp)->def != NULL && attr->def == NULL) {
02054                                    attr->def = estrdup((*tmp)->def);
02055                             }
02056                             if ((*tmp)->fixed != NULL && attr->fixed == NULL) {
02057                                    attr->fixed = estrdup((*tmp)->fixed);
02058                             }
02059                             if (attr->form == XSD_FORM_DEFAULT) {
02060                                    attr->form = (*tmp)->form;
02061                             }
02062                             if (attr->use == XSD_USE_DEFAULT) {
02063                                    attr->use  = (*tmp)->use;
02064                             }
02065                             if ((*tmp)->extraAttributes != NULL) {
02066                               xmlNodePtr node;
02067 
02068                                    attr->extraAttributes = emalloc(sizeof(HashTable));
02069                                    zend_hash_init(attr->extraAttributes, zend_hash_num_elements((*tmp)->extraAttributes), NULL, delete_extra_attribute, 0);
02070                                    zend_hash_copy(attr->extraAttributes, (*tmp)->extraAttributes, copy_extra_attribute, &node, sizeof(xmlNodePtr));
02071                             }
02072                             attr->encode = (*tmp)->encode;
02073                      }
02074               }
02075               if (attr->name == NULL && attr->ref != NULL) {
02076                      char *name = strrchr(attr->ref, ':');
02077                      if (name) {
02078                             attr->name = estrdup(name+1);
02079                      } else{
02080                             attr->name = estrdup(attr->ref);
02081                      }
02082               }
02083               efree(attr->ref);
02084               attr->ref = NULL;
02085        }
02086 }
02087 
02088 static void schema_attributegroup_fixup(sdlCtx *ctx, sdlAttributePtr attr, HashTable *ht)
02089 {
02090        sdlTypePtr *tmp;
02091        sdlAttributePtr *tmp_attr;
02092 
02093        if (attr->ref != NULL) {
02094               if (ctx->attributeGroups != NULL) {
02095                      if (zend_hash_find(ctx->attributeGroups, attr->ref, strlen(attr->ref)+1, (void**)&tmp) == SUCCESS) {
02096                             if ((*tmp)->attributes) {
02097                                    zend_hash_internal_pointer_reset((*tmp)->attributes);
02098                                    while (zend_hash_get_current_data((*tmp)->attributes,(void**)&tmp_attr) == SUCCESS) {
02099                                           if (zend_hash_get_current_key_type((*tmp)->attributes) == HASH_KEY_IS_STRING) {
02100                                                  char* key;
02101                                                  uint key_len;
02102                                                  sdlAttributePtr newAttr;
02103 
02104                                                  schema_attribute_fixup(ctx,*tmp_attr);
02105 
02106                                                  newAttr = emalloc(sizeof(sdlAttribute));
02107                                                  memcpy(newAttr, *tmp_attr, sizeof(sdlAttribute));
02108                                                  if (newAttr->def) {newAttr->def = estrdup(newAttr->def);}
02109                                                  if (newAttr->fixed) {newAttr->fixed = estrdup(newAttr->fixed);}
02110                                                  if (newAttr->namens) {newAttr->namens = estrdup(newAttr->namens);}
02111                                                  if (newAttr->name) {newAttr->name = estrdup(newAttr->name);}
02112                                                  if (newAttr->extraAttributes) {
02113                                                    xmlNodePtr node;
02114                                                         HashTable *ht = emalloc(sizeof(HashTable));
02115                                                         zend_hash_init(ht, zend_hash_num_elements(newAttr->extraAttributes), NULL, delete_extra_attribute, 0);
02116                                                         zend_hash_copy(ht, newAttr->extraAttributes, copy_extra_attribute, &node, sizeof(xmlNodePtr));
02117                                                         newAttr->extraAttributes = ht;
02118                                                  }
02119 
02120                                                  zend_hash_get_current_key_ex((*tmp)->attributes, &key, &key_len, NULL, 0, NULL);
02121                                                  zend_hash_add(ht, key, key_len, &newAttr, sizeof(sdlAttributePtr), NULL);
02122 
02123                                                  zend_hash_move_forward((*tmp)->attributes);
02124                                           } else {
02125                                                  ulong index;
02126 
02127                                                  schema_attributegroup_fixup(ctx,*tmp_attr, ht);
02128                                                  zend_hash_get_current_key((*tmp)->attributes, NULL, &index, 0);
02129                                                  zend_hash_index_del((*tmp)->attributes, index);
02130                                           }
02131                                    }
02132                             }
02133                      }
02134               }
02135               efree(attr->ref);
02136               attr->ref = NULL;
02137        }
02138 }
02139 
02140 static void schema_content_model_fixup(sdlCtx *ctx, sdlContentModelPtr model)
02141 {
02142        switch (model->kind) {
02143               case XSD_CONTENT_GROUP_REF: {
02144                      sdlTypePtr *tmp;
02145 
02146                      if (ctx->sdl->groups && zend_hash_find(ctx->sdl->groups, model->u.group_ref, strlen(model->u.group_ref)+1, (void**)&tmp) == SUCCESS) {
02147                             schema_type_fixup(ctx,*tmp);
02148                             efree(model->u.group_ref);
02149                             model->kind = XSD_CONTENT_GROUP;
02150                             model->u.group = (*tmp);
02151                      } else {
02152                             soap_error0(E_ERROR, "Parsing Schema: unresolved group 'ref' attribute");
02153                      }
02154                      break;
02155               }
02156               case XSD_CONTENT_CHOICE: {
02157                      if (model->max_occurs != 1) {
02158                             HashPosition pos;
02159                             sdlContentModelPtr *tmp;
02160 
02161                             zend_hash_internal_pointer_reset_ex(model->u.content, &pos);
02162                             while (zend_hash_get_current_data_ex(model->u.content, (void**)&tmp, &pos) == SUCCESS) {
02163                                    (*tmp)->min_occurs = 0;
02164                                    (*tmp)->max_occurs = model->max_occurs;
02165                                    zend_hash_move_forward_ex(model->u.content, &pos);
02166                             }
02167 
02168                             model->kind = XSD_CONTENT_ALL;
02169                             model->min_occurs = 1;
02170                             model->max_occurs = 1;
02171                      }
02172               }
02173               case XSD_CONTENT_SEQUENCE:
02174               case XSD_CONTENT_ALL: {
02175                      sdlContentModelPtr *tmp;
02176 
02177                      zend_hash_internal_pointer_reset(model->u.content);
02178                      while (zend_hash_get_current_data(model->u.content, (void**)&tmp) == SUCCESS) {
02179                             schema_content_model_fixup(ctx, *tmp);
02180                             zend_hash_move_forward(model->u.content);
02181                      }
02182                      break;
02183               }
02184               default:
02185                      break;
02186        }
02187 }
02188 
02189 static void schema_type_fixup(sdlCtx *ctx, sdlTypePtr type)
02190 {
02191        sdlTypePtr *tmp;
02192        sdlAttributePtr *attr;
02193 
02194        if (type->ref != NULL) {
02195               if (ctx->sdl->elements != NULL) {
02196                      if (zend_hash_find(ctx->sdl->elements, type->ref, strlen(type->ref)+1, (void**)&tmp) == SUCCESS) {
02197                             type->kind = (*tmp)->kind;
02198                             type->encode = (*tmp)->encode;
02199                             if ((*tmp)->nillable) {
02200                               type->nillable = 1;
02201                             }
02202                             if ((*tmp)->fixed) {
02203                               type->fixed = estrdup((*tmp)->fixed);
02204                             }
02205                             if ((*tmp)->def) {
02206                               type->def = estrdup((*tmp)->def);
02207                             }
02208                             type->form = (*tmp)->form;
02209                      } else if (strcmp(type->ref, SCHEMA_NAMESPACE ":schema") == 0) {
02210                             type->encode = get_conversion(XSD_ANYXML);
02211                      } else {
02212                             soap_error0(E_ERROR, "Parsing Schema: unresolved element 'ref' attribute");
02213                      }
02214               }
02215               efree(type->ref);
02216               type->ref = NULL;
02217        }
02218        if (type->elements) {
02219               zend_hash_internal_pointer_reset(type->elements);
02220               while (zend_hash_get_current_data(type->elements,(void**)&tmp) == SUCCESS) {
02221                      schema_type_fixup(ctx,*tmp);
02222                      zend_hash_move_forward(type->elements);
02223               }
02224        }
02225        if (type->model) {
02226               schema_content_model_fixup(ctx, type->model);
02227        }
02228        if (type->attributes) {
02229               zend_hash_internal_pointer_reset(type->attributes);
02230               while (zend_hash_get_current_data(type->attributes,(void**)&attr) == SUCCESS) {
02231                      if (zend_hash_get_current_key_type(type->attributes) == HASH_KEY_IS_STRING) {
02232                             schema_attribute_fixup(ctx,*attr);
02233                             zend_hash_move_forward(type->attributes);
02234                      } else {
02235                             ulong index;
02236 
02237                             schema_attributegroup_fixup(ctx,*attr,type->attributes);
02238                             zend_hash_get_current_key(type->attributes, NULL, &index, 0);
02239                             zend_hash_index_del(type->attributes, index);
02240                      }
02241               }
02242        }
02243 }
02244 
02245 void schema_pass2(sdlCtx *ctx)
02246 {
02247        sdlPtr sdl = ctx->sdl;
02248        sdlAttributePtr *attr;
02249        sdlTypePtr *type;
02250 
02251        if (ctx->attributes) {
02252               zend_hash_internal_pointer_reset(ctx->attributes);
02253               while (zend_hash_get_current_data(ctx->attributes,(void**)&attr) == SUCCESS) {
02254                      schema_attribute_fixup(ctx,*attr);
02255                      zend_hash_move_forward(ctx->attributes);
02256               }
02257        }
02258        if (ctx->attributeGroups) {
02259               zend_hash_internal_pointer_reset(ctx->attributeGroups);
02260               while (zend_hash_get_current_data(ctx->attributeGroups,(void**)&type) == SUCCESS) {
02261                      schema_type_fixup(ctx,*type);
02262                      zend_hash_move_forward(ctx->attributeGroups);
02263               }
02264        }
02265        if (sdl->elements) {
02266               zend_hash_internal_pointer_reset(sdl->elements);
02267               while (zend_hash_get_current_data(sdl->elements,(void**)&type) == SUCCESS) {
02268                      schema_type_fixup(ctx,*type);
02269                      zend_hash_move_forward(sdl->elements);
02270               }
02271        }
02272        if (sdl->groups) {
02273               zend_hash_internal_pointer_reset(sdl->groups);
02274               while (zend_hash_get_current_data(sdl->groups,(void**)&type) == SUCCESS) {
02275                      schema_type_fixup(ctx,*type);
02276                      zend_hash_move_forward(sdl->groups);
02277               }
02278        }
02279        if (sdl->types) {
02280               zend_hash_internal_pointer_reset(sdl->types);
02281               while (zend_hash_get_current_data(sdl->types,(void**)&type) == SUCCESS) {
02282                      schema_type_fixup(ctx,*type);
02283                      zend_hash_move_forward(sdl->types);
02284               }
02285        }
02286        if (ctx->attributes) {
02287               zend_hash_destroy(ctx->attributes);
02288               efree(ctx->attributes);
02289        }
02290        if (ctx->attributeGroups) {
02291               zend_hash_destroy(ctx->attributeGroups);
02292               efree(ctx->attributeGroups);
02293        }
02294 }
02295 
02296 void delete_model(void *handle)
02297 {
02298        sdlContentModelPtr tmp = *((sdlContentModelPtr*)handle);
02299        switch (tmp->kind) {
02300               case XSD_CONTENT_ELEMENT:
02301               case XSD_CONTENT_GROUP:
02302                      break;
02303               case XSD_CONTENT_SEQUENCE:
02304               case XSD_CONTENT_ALL:
02305               case XSD_CONTENT_CHOICE:
02306                      zend_hash_destroy(tmp->u.content);
02307                      efree(tmp->u.content);
02308                      break;
02309               case XSD_CONTENT_GROUP_REF:
02310                      efree(tmp->u.group_ref);
02311                      break;
02312               default:
02313                      break;
02314        }
02315        efree(tmp);
02316 }
02317 
02318 void delete_model_persistent(void *handle)
02319 {
02320        sdlContentModelPtr tmp = *((sdlContentModelPtr*)handle);
02321        switch (tmp->kind) {
02322               case XSD_CONTENT_ELEMENT:
02323               case XSD_CONTENT_GROUP:
02324                      break;
02325               case XSD_CONTENT_SEQUENCE:
02326               case XSD_CONTENT_ALL:
02327               case XSD_CONTENT_CHOICE:
02328                      zend_hash_destroy(tmp->u.content);
02329                      free(tmp->u.content);
02330                      break;
02331               case XSD_CONTENT_GROUP_REF:
02332                      free(tmp->u.group_ref);
02333                      break;
02334               default:
02335                      break;
02336        }
02337        free(tmp);
02338 }
02339 
02340 void delete_type(void *data)
02341 {
02342        sdlTypePtr type = *((sdlTypePtr*)data);
02343 
02344        if (type->name) {
02345               efree(type->name);
02346        }
02347        if (type->namens) {
02348               efree(type->namens);
02349        }
02350        if (type->def) {
02351               efree(type->def);
02352        }
02353        if (type->fixed) {
02354               efree(type->fixed);
02355        }
02356        if (type->elements) {
02357               zend_hash_destroy(type->elements);
02358               efree(type->elements);
02359        }
02360        if (type->attributes) {
02361               zend_hash_destroy(type->attributes);
02362               efree(type->attributes);
02363        }
02364        if (type->model) {
02365               delete_model((void**)&type->model);
02366        }
02367        if (type->restrictions) {
02368               delete_restriction_var_int(&type->restrictions->minExclusive);
02369               delete_restriction_var_int(&type->restrictions->minInclusive);
02370               delete_restriction_var_int(&type->restrictions->maxExclusive);
02371               delete_restriction_var_int(&type->restrictions->maxInclusive);
02372               delete_restriction_var_int(&type->restrictions->totalDigits);
02373               delete_restriction_var_int(&type->restrictions->fractionDigits);
02374               delete_restriction_var_int(&type->restrictions->length);
02375               delete_restriction_var_int(&type->restrictions->minLength);
02376               delete_restriction_var_int(&type->restrictions->maxLength);
02377               delete_restriction_var_char(&type->restrictions->whiteSpace);
02378               delete_restriction_var_char(&type->restrictions->pattern);
02379               if (type->restrictions->enumeration) {
02380                      zend_hash_destroy(type->restrictions->enumeration);
02381                      efree(type->restrictions->enumeration);
02382               }
02383               efree(type->restrictions);
02384        }
02385        efree(type);
02386 }
02387 
02388 void delete_type_persistent(void *data)
02389 {
02390        sdlTypePtr type = *((sdlTypePtr*)data);
02391        if (type->name) {
02392               free(type->name);
02393        }
02394        if (type->namens) {
02395               free(type->namens);
02396        }
02397        if (type->def) {
02398               free(type->def);
02399        }
02400        if (type->fixed) {
02401               free(type->fixed);
02402        }
02403        if (type->elements) {
02404               zend_hash_destroy(type->elements);
02405               free(type->elements);
02406        }
02407        if (type->attributes) {
02408               zend_hash_destroy(type->attributes);
02409               free(type->attributes);
02410        }
02411        if (type->model) {
02412               delete_model_persistent((void**)&type->model);
02413        }
02414        if (type->restrictions) {
02415               delete_restriction_var_int_persistent(&type->restrictions->minExclusive);
02416               delete_restriction_var_int_persistent(&type->restrictions->minInclusive);
02417               delete_restriction_var_int_persistent(&type->restrictions->maxExclusive);
02418               delete_restriction_var_int_persistent(&type->restrictions->maxInclusive);
02419               delete_restriction_var_int_persistent(&type->restrictions->totalDigits);
02420               delete_restriction_var_int_persistent(&type->restrictions->fractionDigits);
02421               delete_restriction_var_int_persistent(&type->restrictions->length);
02422               delete_restriction_var_int_persistent(&type->restrictions->minLength);
02423               delete_restriction_var_int_persistent(&type->restrictions->maxLength);
02424               delete_restriction_var_char_persistent(&type->restrictions->whiteSpace);
02425               delete_restriction_var_char_persistent(&type->restrictions->pattern);
02426               if (type->restrictions->enumeration) {
02427                      zend_hash_destroy(type->restrictions->enumeration);
02428                      free(type->restrictions->enumeration);
02429               }
02430               free(type->restrictions);
02431        }
02432        free(type);
02433 }
02434 
02435 void delete_extra_attribute(void *attribute)
02436 {
02437        sdlExtraAttributePtr attr = *((sdlExtraAttributePtr*)attribute);
02438 
02439        if (attr->ns) {
02440               efree(attr->ns);
02441        }
02442        if (attr->val) {
02443               efree(attr->val);
02444        }
02445        efree(attr);
02446 }
02447 
02448 void delete_extra_attribute_persistent(void *attribute)
02449 {
02450        sdlExtraAttributePtr attr = *((sdlExtraAttributePtr*)attribute);
02451 
02452        if (attr->ns) {
02453               free(attr->ns);
02454        }
02455        if (attr->val) {
02456               free(attr->val);
02457        }
02458        free(attr);
02459 }
02460 
02461 void delete_attribute(void *attribute)
02462 {
02463        sdlAttributePtr attr = *((sdlAttributePtr*)attribute);
02464 
02465        if (attr->def) {
02466               efree(attr->def);
02467        }
02468        if (attr->fixed) {
02469               efree(attr->fixed);
02470        }
02471        if (attr->name) {
02472               efree(attr->name);
02473        }
02474        if (attr->namens) {
02475               efree(attr->namens);
02476        }
02477        if (attr->ref) {
02478               efree(attr->ref);
02479        }
02480        if (attr->extraAttributes) {
02481               zend_hash_destroy(attr->extraAttributes);
02482               efree(attr->extraAttributes);
02483        }
02484        efree(attr);
02485 }
02486 
02487 void delete_attribute_persistent(void *attribute)
02488 {
02489        sdlAttributePtr attr = *((sdlAttributePtr*)attribute);
02490 
02491        if (attr->def) {
02492               free(attr->def);
02493        }
02494        if (attr->fixed) {
02495               free(attr->fixed);
02496        }
02497        if (attr->name) {
02498               free(attr->name);
02499        }
02500        if (attr->namens) {
02501               free(attr->namens);
02502        }
02503        if (attr->ref) {
02504               free(attr->ref);
02505        }
02506        if (attr->extraAttributes) {
02507               zend_hash_destroy(attr->extraAttributes);
02508               free(attr->extraAttributes);
02509        }
02510        free(attr);
02511 }
02512 
02513 void delete_restriction_var_int(void *rvi)
02514 {
02515        sdlRestrictionIntPtr ptr = *((sdlRestrictionIntPtr*)rvi);
02516        if (ptr) {
02517               efree(ptr);
02518        }
02519 }
02520 
02521 void delete_restriction_var_int_persistent(void *rvi)
02522 {
02523        sdlRestrictionIntPtr ptr = *((sdlRestrictionIntPtr*)rvi);
02524        if (ptr) {
02525               free(ptr);
02526        }
02527 }
02528 
02529 void delete_restriction_var_char(void *srvc)
02530 {
02531        sdlRestrictionCharPtr ptr = *((sdlRestrictionCharPtr*)srvc);
02532        if (ptr) {
02533               if (ptr->value) {
02534                      efree(ptr->value);
02535               }
02536               efree(ptr);
02537        }
02538 }
02539 
02540 void delete_restriction_var_char_persistent(void *srvc)
02541 {
02542        sdlRestrictionCharPtr ptr = *((sdlRestrictionCharPtr*)srvc);
02543        if (ptr) {
02544               if (ptr->value) {
02545                      free(ptr->value);
02546               }
02547               free(ptr);
02548        }
02549 }