]> granicus.if.org Git - php/commitdiff
XML Schema support
authorDmitry Stogov <dmitry@php.net>
Tue, 20 Jan 2004 16:30:38 +0000 (16:30 +0000)
committerDmitry Stogov <dmitry@php.net>
Tue, 20 Jan 2004 16:30:38 +0000 (16:30 +0000)
  - support for <element> 'ref' attibute was implemented
  - support for inline types
  - support for <list> and <union> (incompleate)

ext/soap/TODO
ext/soap/php_encoding.c
ext/soap/php_encoding.h
ext/soap/php_schema.c
ext/soap/php_schema.h
ext/soap/php_sdl.c
ext/soap/php_sdl.h
ext/soap/soap.c

index b8a27cfd3718a03ae3d2f96199ad6671fd5d3717..9eb2d0d46afd81426f0b25857d1f1a8a6fc76fcc 100644 (file)
@@ -100,7 +100,7 @@ Schema
 ------
 - <include>, <import>, <redefine>
 - support for user defined simple types
-  - restiction
+  ? restiction
          + base
          + enumeration
                + length (for string, anyURI, hexBinary, base64Binary and derived)
@@ -114,8 +114,8 @@ Schema
                - maxInclusive (for numeric, date types)
                - totalDigits (for decimal)
                - fractionDigits (for decimal)
-       - list ???
-       - union ???
+       ? list
+       ? union
 - support for user defined complex types
   - simpleContent extension   
   + base
index 38d61143352476cdab8b81c868179e2ee249425d..b4acf1001a23c6d2dfa685633ee94043b03a5d0f 100644 (file)
@@ -45,7 +45,6 @@ static int is_map(zval *array);
 static void get_array_type(xmlNodePtr node, zval *array, smart_str *out_type TSRMLS_DC);
 
 static void get_type_str(xmlNodePtr node, const char* ns, const char* type, smart_str* ret);
-static void set_ns_and_type(xmlNodePtr node, encodeType type);
 static void set_ns_and_type_ex(xmlNodePtr node, char *ns, char *type);
 
 encode defaultEncoding[] = {
@@ -179,6 +178,9 @@ xmlNodePtr master_to_xml(encodePtr encode, zval *data, int style)
 {
        xmlNodePtr node = NULL;
 
+       if (encode == NULL) {
+               encode = get_conversion(UNKNOWN_TYPE);          
+       }
        if (encode->to_xml_before) {
                data = encode->to_xml_before(encode->details, data);
        }
@@ -1598,7 +1600,7 @@ static xmlNodePtr to_xml_gmonth(encodeType type, zval *data, int style)
        return to_xml_datetime_ex(type, data, "--%m--", style);
 }
 
-static void set_ns_and_type(xmlNodePtr node, encodeType type)
+void set_ns_and_type(xmlNodePtr node, encodeType type)
 {
        set_ns_and_type_ex(node, type.ns, type.type_str);
 }
@@ -1794,21 +1796,35 @@ static void get_type_str(xmlNodePtr node, const char* ns, const char* type, smar
                        smart_str_appendl(ret, prefix, strlen(prefix));
                        smart_str_appendc(ret, ':');
                } else  if (node != NULL) {
-                       smart_str* prefix = encode_new_ns();
-                       smart_str xmlns = {0};
+                       xmlAttrPtr attr = node->properties;
 
-                       smart_str_appendl(&xmlns, "xmlns:", 6);
-                       smart_str_append(&xmlns, prefix);
-                       smart_str_0(&xmlns);
+                       while (attr != NULL) {
+                               if (strncmp(attr->name,"xmlns:",sizeof("xmlns:")-1) == 0 &&
+                                   strcmp(attr->children->content,ns) == 0) {
+                                       break;
+                               }
+                         attr = attr->next;
+                       }
+                       if (attr == NULL) {
+                               smart_str* prefix = encode_new_ns();
+                               smart_str xmlns = {0};
 
-                       xmlSetProp(node, xmlns.c, ns);
+                               smart_str_appendl(&xmlns, "xmlns:", 6);
+                               smart_str_append(&xmlns, prefix);
+                               smart_str_0(&xmlns);
 
-                       smart_str_append(ret, prefix);
-                       smart_str_appendc(ret, ':');
+                               xmlSetProp(node, xmlns.c, ns);
 
-                       smart_str_free(&xmlns);
-                       smart_str_free(prefix);
-                       efree(prefix);
+                               smart_str_append(ret, prefix);
+                               smart_str_appendc(ret, ':');
+
+                               smart_str_free(&xmlns);
+                               smart_str_free(prefix);
+                               efree(prefix);
+                       } else {
+                               smart_str_appends(ret, attr->name + sizeof("xmlns:")-1);
+                               smart_str_appendc(ret, ':');
+                       }
                } else {
                        php_error(E_ERROR,"Unknown namespace '%s'",ns);
                }
index 85b99898932034a4c5f23422f7436979f6833278..7b30f0a1fb836727f13342f15d6bff40909f34b5 100644 (file)
@@ -198,6 +198,7 @@ xmlNodePtr guess_xml_convert(encodeType type, zval *data, int style);
 
 void encode_reset_ns();
 smart_str *encode_new_ns();
+void set_ns_and_type(xmlNodePtr node, encodeType type);
 
 encodePtr get_conversion_ex(HashTable *encoding, int encode);
 encodePtr get_conversion_from_type_ex(HashTable *encoding, xmlNodePtr node, const char *type);
index bd42c646433a8a18e0e3ee73a27fadab42942abf..3ff2502b33ca67c561d2b947867070708916a1f5 100644 (file)
@@ -6,7 +6,7 @@ static int schema_sequence(sdlPtr sdl, xmlAttrPtr tsn, xmlNodePtr seqType, sdlTy
 static int schema_list(sdlPtr sdl, xmlAttrPtr tsn, xmlNodePtr listType, sdlTypePtr cur_type);
 static int schema_union(sdlPtr sdl, xmlAttrPtr tsn, xmlNodePtr unionType, sdlTypePtr cur_type);
 static int schema_simpleContent(sdlPtr sdl, xmlAttrPtr tsn, xmlNodePtr simpCompType, sdlTypePtr cur_type);
-static int schema_restriction_simpleContent(sdlPtr sdl, xmlAttrPtr tsn, xmlNodePtr restType, sdlTypePtr cur_type);
+static int schema_restriction_simpleContent(sdlPtr sdl, xmlAttrPtr tsn, xmlNodePtr restType, sdlTypePtr cur_type, int simpleType);
 static int schema_restriction_complexContent(sdlPtr sdl, xmlAttrPtr tsn, xmlNodePtr restType, sdlTypePtr cur_type);
 static int schema_extension_simpleContent(sdlPtr sdl, xmlAttrPtr tsn, xmlNodePtr extType, sdlTypePtr cur_type);
 static int schema_extension_complexContent(sdlPtr sdl, xmlAttrPtr tsn, xmlNodePtr extType, sdlTypePtr cur_type);
@@ -123,11 +123,44 @@ static int schema_simpleType(sdlPtr sdl, xmlAttrPtr tsn, xmlNodePtr simpleType,
        }
 
        name = get_attribute(simpleType->properties, "name");
-       if (name != NULL) {
+       if (cur_type != NULL) {
+               /* Anonymous type inside <element> or <restriction> */
+               sdlTypePtr newType, *ptr;
+
+               newType = malloc(sizeof(sdlType));
+               memset(newType, 0, sizeof(sdlType));
+               newType->kind = XSD_TYPEKIND_SIMPLE;
+               if (name != NULL) {
+                       newType->name = strdup(name->children->content);
+                       newType->namens = strdup(ns->children->content);
+               } else {
+                       newType->name = strdup(cur_type->name);
+                       newType->namens = strdup(cur_type->namens);
+               }
+
+               zend_hash_next_index_insert(sdl->types,  &newType, sizeof(sdlTypePtr), (void **)&ptr);
+
+               if (sdl->encoders == NULL) {
+                       sdl->encoders = malloc(sizeof(HashTable));
+                       zend_hash_init(sdl->encoders, 0, NULL, delete_encoder, 1);
+               }
+               cur_type->encode = malloc(sizeof(encode));
+               memset(cur_type->encode, 0, sizeof(encode));
+               cur_type->encode->details.ns = strdup(newType->namens);
+               cur_type->encode->details.type_str = strdup(newType->name);
+               cur_type->encode->details.sdl_type = *ptr;
+               cur_type->encode->to_xml = sdl_guess_convert_xml;
+               cur_type->encode->to_zval = sdl_guess_convert_zval;
+               zend_hash_next_index_insert(sdl->encoders,  &cur_type->encode, sizeof(encodePtr), NULL);
+
+               cur_type =*ptr;
+
+       } else if (name != NULL) {
                sdlTypePtr newType, *ptr;
 
                newType = malloc(sizeof(sdlType));
                memset(newType, 0, sizeof(sdlType));
+               newType->kind = XSD_TYPEKIND_SIMPLE;
                newType->name = strdup(name->children->content);
                newType->namens = strdup(ns->children->content);
 
@@ -143,17 +176,6 @@ static int schema_simpleType(sdlPtr sdl, xmlAttrPtr tsn, xmlNodePtr simpleType,
                cur_type = (*ptr);
 
                create_encoder(sdl, cur_type, ns->children->content, name->children->content);
-       } else if (cur_type != NULL) {
-               sdlTypePtr newType, *ptr;
-
-               newType = malloc(sizeof(sdlType));
-               memset(newType, 0, sizeof(sdlType));
-               newType->name = strdup(cur_type->name);
-               newType->namens = strdup(cur_type->namens);
-
-               zend_hash_next_index_insert(sdl->types,  &newType, sizeof(sdlTypePtr), (void **)&ptr);
-               cur_type->encode = create_encoder(sdl, *ptr, (char *)(*ptr)->namens, (char *)(*ptr)->name);
-               cur_type =*ptr;
        } else {
                php_error(E_ERROR, "Error parsing schema (simpleType has no 'name' attribute)");
        }
@@ -171,17 +193,21 @@ static int schema_simpleType(sdlPtr sdl, xmlAttrPtr tsn, xmlNodePtr simpleType,
        }
        if (trav != NULL) {
                if (node_is_equal(trav,"restriction")) {
-                       schema_restriction_simpleContent(sdl, tsn, trav, cur_type);
+                       schema_restriction_simpleContent(sdl, tsn, trav, cur_type, 1);
                        trav = trav->next;
                } else if (node_is_equal(trav,"list")) {
+                       cur_type->kind = XSD_TYPEKIND_LIST;
                        schema_list(sdl, tsn, trav, cur_type);
                        trav = trav->next;
                } else if (node_is_equal(trav,"union")) {
+                       cur_type->kind = XSD_TYPEKIND_UNION;
                        schema_union(sdl, tsn, trav, cur_type);
                        trav = trav->next;
                } else {
                        php_error(E_ERROR, "Error parsing schema (unexpected <%s> in simpleType)",trav->name);
                }
+       } else {
+               php_error(E_ERROR, "Error parsing schema (expected <restriction>, <list> or <union> in simpleType)");
        }
        while (trav != NULL && trav->type != XML_ELEMENT_NODE) {
                trav = trav->next;
@@ -208,7 +234,30 @@ static int schema_list(sdlPtr sdl, xmlAttrPtr tsn, xmlNodePtr listType, sdlTypeP
 
        itemType = get_attribute(listType->properties, "itemType");
        if (itemType != NULL) {
-               /*FIXME*/
+               char *type, *ns;
+               xmlNsPtr nsptr;
+
+               parse_namespace(itemType->children->content, &type, &ns);
+               nsptr = xmlSearchNs(listType->doc, listType, ns);
+               if (nsptr != NULL) {
+                       sdlTypePtr newType, *tmp;
+
+                       newType = malloc(sizeof(sdlType));
+                       memset(newType, 0, sizeof(sdlType));
+
+                       newType->name = strdup(type);
+                       newType->namens = strdup(nsptr->href);
+
+                       newType->encode = get_create_encoder(sdl, newType, (char *)nsptr->href, type);
+
+                       if (cur_type->elements == NULL) {
+                               cur_type->elements = malloc(sizeof(HashTable));
+                               zend_hash_init(cur_type->elements, 0, NULL, delete_type, 1);
+                       }
+                       zend_hash_next_index_insert(cur_type->elements, &newType, sizeof(sdlTypePtr), (void **)&tmp);                   
+               }
+               if (type) {efree(type);}
+               if (ns) {efree(ns);}
        }
 
        trav = listType->children;
@@ -223,7 +272,25 @@ static int schema_list(sdlPtr sdl, xmlAttrPtr tsn, xmlNodePtr listType, sdlTypeP
                trav = trav->next;
        }
        if (trav != NULL && node_is_equal(trav,"simpleType")) {
-               /*FIXME*/
+               sdlTypePtr newType, *tmp;
+
+               if (itemType != NULL) {
+                       php_error(E_ERROR, "Error parsing schema (element have both 'itemType' attribute and subtype)");
+               }
+
+               newType = malloc(sizeof(sdlType));
+               memset(newType, 0, sizeof(sdlType));
+
+               newType->name = strdup("anonymous");
+               newType->namens = strdup(tsn->children->content);
+
+               if (cur_type->elements == NULL) {
+                       cur_type->elements = malloc(sizeof(HashTable));
+                       zend_hash_init(cur_type->elements, 0, NULL, delete_type, 1);
+               }
+               zend_hash_next_index_insert(cur_type->elements, &newType, sizeof(sdlTypePtr), (void **)&tmp);                   
+
+               schema_simpleType(sdl, tsn, trav, newType);
          trav = trav->next;
        }
        while (trav != NULL && trav->type != XML_ELEMENT_NODE) {
@@ -246,11 +313,51 @@ static int schema_list(sdlPtr sdl, xmlAttrPtr tsn, xmlNodePtr listType, sdlTypeP
 static int schema_union(sdlPtr sdl, xmlAttrPtr tsn, xmlNodePtr unionType, sdlTypePtr cur_type)
 {
        xmlNodePtr trav;
-       xmlAttrPtr itemType;
+       xmlAttrPtr memberTypes;
 
-       itemType = get_attribute(unionType->properties, "memberTypes");
-       if (itemType != NULL) {
-               /*FIXME*/
+       memberTypes = get_attribute(unionType->properties, "memberTypes");
+       if (memberTypes != NULL) {
+               char *str, *start, *end, *next;
+               char *type, *ns;
+               xmlNsPtr nsptr;
+
+               str = estrdup(memberTypes->children->content);
+               whiteSpace_collapse(str);
+               start = str;
+               while (start != NULL && *start != '\0') {
+                       end = strchr(start,' ');
+                       if (end == NULL) {
+                         next = NULL;
+                       } else {
+                         *end = '\0';
+                         next = end+1;
+                       }
+
+                       parse_namespace(start, &type, &ns);
+                       nsptr = xmlSearchNs(unionType->doc, unionType, ns);
+                       if (nsptr != NULL) {
+                               sdlTypePtr newType, *tmp;
+
+                               newType = malloc(sizeof(sdlType));
+                               memset(newType, 0, sizeof(sdlType));
+
+                               newType->name = strdup(type);
+                               newType->namens = strdup(nsptr->href);
+
+                               newType->encode = get_create_encoder(sdl, newType, (char *)nsptr->href, type);
+
+                               if (cur_type->elements == NULL) {
+                                       cur_type->elements = malloc(sizeof(HashTable));
+                                       zend_hash_init(cur_type->elements, 0, NULL, delete_type, 1);
+                               }
+                               zend_hash_next_index_insert(cur_type->elements, &newType, sizeof(sdlTypePtr), (void **)&tmp);                   
+                       }
+                       if (type) {efree(type);}
+                       if (ns) {efree(ns);}
+
+                       start = next;
+               }
+               efree(str);
        }
 
        trav = unionType->children;
@@ -264,7 +371,26 @@ static int schema_union(sdlPtr sdl, xmlAttrPtr tsn, xmlNodePtr unionType, sdlTyp
        while (trav != NULL) {
                if (trav->type == XML_ELEMENT_NODE) {
                        if (node_is_equal(trav,"simpleType")) {
-                               /*FIXME*/
+                               sdlTypePtr newType, *tmp;
+
+                               if (memberTypes != NULL) {
+                                       php_error(E_ERROR, "Error parsing schema (union have both 'memberTypes' attribute and subtypes)");
+                               }
+                               
+                               newType = malloc(sizeof(sdlType));
+                               memset(newType, 0, sizeof(sdlType));
+
+                               newType->name = strdup("anonymous");
+                               newType->namens = strdup(tsn->children->content);
+
+                               if (cur_type->elements == NULL) {
+                                       cur_type->elements = malloc(sizeof(HashTable));
+                                       zend_hash_init(cur_type->elements, 0, NULL, delete_type, 1);
+                               }
+                               zend_hash_next_index_insert(cur_type->elements, &newType, sizeof(sdlTypePtr), (void **)&tmp);                   
+
+                               schema_simpleType(sdl, tsn, trav, newType);
+
                        } else {
                                php_error(E_ERROR, "Error parsing schema (unexpected <%s> in union)",trav->name);
                        }
@@ -304,7 +430,7 @@ static int schema_simpleContent(sdlPtr sdl, xmlAttrPtr tsn, xmlNodePtr simpCompT
        }
        if (trav != NULL) {
                if (node_is_equal(trav, "restriction")) {
-                       schema_restriction_simpleContent(sdl, tsn, trav, cur_type);
+                       schema_restriction_simpleContent(sdl, tsn, trav, cur_type, 0);
                        trav = trav->next;
                } else if (node_is_equal(trav, "extension")) {
                        schema_extension_simpleContent(sdl, tsn, trav, cur_type);
@@ -326,14 +452,20 @@ static int schema_simpleContent(sdlPtr sdl, xmlAttrPtr tsn, xmlNodePtr simpCompT
 }
 
 /*
-<restriction
+simpleType:<restriction
+  base = QName
+  id = ID
+  {any attributes with non-schema namespace . . .}>
+  Content: (annotation?, (simpleType?, (minExclusive | minInclusive | maxExclusive | maxInclusive | totalDigits | fractionDigits | length | minLength | maxLength | enumeration | whiteSpace | pattern)*)?)
+</restriction>
+simpleContent:<restriction
   base = QName
   id = ID
   {any attributes with non-schema namespace . . .}>
   Content: (annotation?, (simpleType?, (minExclusive | minInclusive | maxExclusive | maxInclusive | totalDigits | fractionDigits | length | minLength | maxLength | enumeration | whiteSpace | pattern)*)?, ((attribute | attributeGroup)*, anyAttribute?))
 </restriction>
 */
-static int schema_restriction_simpleContent(sdlPtr sdl, xmlAttrPtr tsn, xmlNodePtr restType, sdlTypePtr cur_type)
+static int schema_restriction_simpleContent(sdlPtr sdl, xmlAttrPtr tsn, xmlNodePtr restType, sdlTypePtr cur_type, int simpleType)
 {
        xmlNodePtr trav;
        xmlAttrPtr base;
@@ -350,6 +482,8 @@ static int schema_restriction_simpleContent(sdlPtr sdl, xmlAttrPtr tsn, xmlNodeP
                }
                if (type) {efree(type);}
                if (ns) {efree(ns);}
+       } else if (!simpleType) {
+               php_error(E_ERROR, "Error parsing schema (restriction has no 'base' attribute)");
        }
 
        if (cur_type->restrictions == NULL) {
@@ -411,21 +545,23 @@ static int schema_restriction_simpleContent(sdlPtr sdl, xmlAttrPtr tsn, xmlNodeP
                }
          trav = trav->next;
        }
-       while (trav != NULL) {
-               if (trav->type == XML_ELEMENT_NODE) {
-                       if (node_is_equal(trav,"attribute")) {
-                               schema_attribute(sdl, tsn, trav, cur_type);
-                       } else if (node_is_equal(trav,"attributeGroup")) {
-                               schema_attributeGroupRef(sdl, tsn, trav, cur_type);
-                       } else if (node_is_equal(trav,"anyAttribute")) {
-                               /* TODO: <anyAttribute> support */
-                               trav = trav->next;
-                               break;
-                       } else {
-                               php_error(E_ERROR, "Error parsing schema (unexpected <%s> in restriction)",trav->name);
+       if (!simpleType) {
+               while (trav != NULL) {
+                       if (trav->type == XML_ELEMENT_NODE) {
+                               if (node_is_equal(trav,"attribute")) {
+                                       schema_attribute(sdl, tsn, trav, cur_type);
+                               } else if (node_is_equal(trav,"attributeGroup")) {
+                                       schema_attributeGroupRef(sdl, tsn, trav, cur_type);
+                               } else if (node_is_equal(trav,"anyAttribute")) {
+                                       /* TODO: <anyAttribute> support */
+                                       trav = trav->next;
+                                       break;
+                               } else {
+                                       php_error(E_ERROR, "Error parsing schema (unexpected <%s> in restriction)",trav->name);
+                               }
                        }
+                       trav = trav->next;
                }
-               trav = trav->next;
        }
        while (trav != NULL && trav->type != XML_ELEMENT_NODE) {
                trav = trav->next;
@@ -482,11 +618,14 @@ static int schema_restriction_complexContent(sdlPtr sdl, xmlAttrPtr tsn, xmlNode
                        schema_group(sdl, tsn, trav, cur_type);
                        trav = trav->next;
                } else if (node_is_equal(trav,"all")) {
+                       cur_type->kind = XSD_TYPEKIND_ALL;
                        schema_all(sdl, tsn, trav, cur_type);
                        trav = trav->next;
                } else if (node_is_equal(trav,"choice")) {
+                       cur_type->kind = XSD_TYPEKIND_CHOICE;
                        schema_choice(sdl, tsn, trav, cur_type);
                        trav = trav->next;
+                       cur_type->kind = XSD_TYPEKIND_SEQUENCE;
                } else if (node_is_equal(trav,"sequence")) {
                        schema_sequence(sdl, tsn, trav, cur_type);
                        trav = trav->next;
@@ -673,12 +812,15 @@ static int schema_extension_complexContent(sdlPtr sdl, xmlAttrPtr tsn, xmlNodePt
                        schema_group(sdl, tsn, trav, cur_type);
                        trav = trav->next;
                } else if (node_is_equal(trav,"all")) {
+                       cur_type->kind = XSD_TYPEKIND_ALL;
                        schema_all(sdl, tsn, trav, cur_type);
                        trav = trav->next;
                } else if (node_is_equal(trav,"choice")) {
+                       cur_type->kind = XSD_TYPEKIND_CHOICE;
                        schema_choice(sdl, tsn, trav, cur_type);
                        trav = trav->next;
                } else if (node_is_equal(trav,"sequence")) {
+                       cur_type->kind = XSD_TYPEKIND_SEQUENCE;
                        schema_sequence(sdl, tsn, trav, cur_type);
                        trav = trav->next;
                }
@@ -772,20 +914,29 @@ static int schema_group(sdlPtr sdl, xmlAttrPtr tsn, xmlNodePtr groupType, sdlTyp
        while (trav != NULL && trav->type != XML_ELEMENT_NODE) {
                trav = trav->next;
        }
-       while (trav != NULL) {
-               if (trav->type == XML_ELEMENT_NODE) {
-                       if (node_is_equal(trav,"choice")) {
-                               schema_choice(sdl, tsn, trav, cur_type);
-                       } else if (node_is_equal(trav,"sequence")) {
-                               schema_sequence(sdl, tsn, trav, cur_type);
-                       } else if (node_is_equal(trav,"all")) {
-                               schema_all(sdl, tsn, trav, cur_type);
-                       } else {
-                               php_error(E_ERROR, "Error parsing schema (unexpected <%s> in group)",trav->name);
-                       }
+       if (trav != NULL) {
+               if (node_is_equal(trav,"choice")) {
+                       cur_type->kind = XSD_TYPEKIND_CHOICE;
+                       schema_choice(sdl, tsn, trav, cur_type);
+                       trav = trav->next;
+               } else if (node_is_equal(trav,"sequence")) {
+                       cur_type->kind = XSD_TYPEKIND_SEQUENCE;
+                       schema_sequence(sdl, tsn, trav, cur_type);
+                       trav = trav->next;
+               } else if (node_is_equal(trav,"all")) {
+                       cur_type->kind = XSD_TYPEKIND_ALL;
+                       schema_all(sdl, tsn, trav, cur_type);
+                       trav = trav->next;
+               } else {
+                       php_error(E_ERROR, "Error parsing schema (unexpected <%s> in group)",trav->name);
                }
+       }
+       while (trav != NULL && trav->type != XML_ELEMENT_NODE) {
                trav = trav->next;
        }
+       if (trav != NULL) {
+               php_error(E_ERROR, "Error parsing schema (unexpected <%s> in group)",trav->name);
+       }
        return TRUE;
 }
 /*
@@ -821,12 +972,16 @@ static int schema_choice(sdlPtr sdl, xmlAttrPtr tsn, xmlNodePtr choiceType, sdlT
                        if (node_is_equal(trav,"element")) {
                                schema_element(sdl, tsn, trav, cur_type);
                        } else if (node_is_equal(trav,"grouop")) {
+                               /*FIXME*/
                                schema_group(sdl, tsn, trav, cur_type);
                        } else if (node_is_equal(trav,"choice")) {
+                               /*FIXME*/
                                schema_choice(sdl, tsn, trav, cur_type);
                        } else if (node_is_equal(trav,"sequence")) {
+                               /*FIXME*/
                                schema_sequence(sdl, tsn, trav, cur_type);
                        } else if (node_is_equal(trav,"any")) {
+                               /*FIXME*/
                                schema_any(sdl, tsn, trav, cur_type);
                        } else {
                                php_error(E_ERROR, "Error parsing schema (unexpected <%s> in choice)",trav->name);
@@ -866,12 +1021,16 @@ static int schema_sequence(sdlPtr sdl, xmlAttrPtr tsn, xmlNodePtr seqType, sdlTy
                        if (node_is_equal(trav,"element")) {
                                schema_element(sdl, tsn, trav, cur_type);
                        } else if (node_is_equal(trav,"grouop")) {
+                               /*FIXME*/
                                schema_group(sdl, tsn, trav, cur_type);
                        } else if (node_is_equal(trav,"choice")) {
+                               /*FIXME*/
                                schema_choice(sdl, tsn, trav, cur_type);
                        } else if (node_is_equal(trav,"sequence")) {
+                               /*FIXME*/
                                schema_sequence(sdl, tsn, trav, cur_type);
                        } else if (node_is_equal(trav,"any")) {
+                               /*FIXME*/
                                schema_any(sdl, tsn, trav, cur_type);
                        } else {
                                php_error(E_ERROR, "Error parsing schema (unexpected <%s> in sequence)",trav->name);
@@ -959,42 +1118,59 @@ static int schema_complexType(sdlPtr sdl, xmlAttrPtr tsn, xmlNodePtr compType, s
        }
 
        name = get_attribute(attrs, "name");
-       if (name) {
+       if (cur_type != NULL) {
+               /* Anonymous type inside <element> */
                sdlTypePtr newType, *ptr;
 
                newType = malloc(sizeof(sdlType));
                memset(newType, 0, sizeof(sdlType));
-               newType->name = strdup(name->children->content);
-               newType->namens = strdup(ns->children->content);
-
-               if (cur_type == NULL) {
-                       zend_hash_next_index_insert(sdl->types,  &newType, sizeof(sdlTypePtr), (void **)&ptr);
+               newType->kind = XSD_TYPEKIND_COMPLEX;
+               if (name != NULL) {
+                       newType->name = strdup(name->children->content);
+                       newType->namens = strdup(ns->children->content);
                } else {
-                       if (cur_type->elements == NULL) {
-                               cur_type->elements = malloc(sizeof(HashTable));
-                               zend_hash_init(cur_type->elements, 0, NULL, delete_type, 1);
-                       }
-                       zend_hash_update(cur_type->elements, newType->name, strlen(newType->name) + 1, &newType, sizeof(sdlTypePtr), (void **)&ptr);
+                       newType->name = strdup(cur_type->name);
+                       newType->namens = strdup(cur_type->namens);
                }
 
-               cur_type = (*ptr);
-               create_encoder(sdl, cur_type, ns->children->content, name->children->content);
-               if (cur_type->encode == NULL) {
-                       cur_type->encode = get_conversion(SOAP_ENC_OBJECT);
+               zend_hash_next_index_insert(sdl->types,  &newType, sizeof(sdlTypePtr), (void **)&ptr);
+
+               if (sdl->encoders == NULL) {
+                       sdl->encoders = malloc(sizeof(HashTable));
+                       zend_hash_init(sdl->encoders, 0, NULL, delete_encoder, 1);
                }
-       } else if (cur_type != NULL) {
+               cur_type->encode = malloc(sizeof(encode));
+               memset(cur_type->encode, 0, sizeof(encode));
+               cur_type->encode->details.ns = strdup(newType->namens);
+               cur_type->encode->details.type_str = strdup(newType->name);
+               cur_type->encode->details.sdl_type = *ptr;
+               cur_type->encode->to_xml = sdl_guess_convert_xml;
+               cur_type->encode->to_zval = sdl_guess_convert_zval;
+               zend_hash_next_index_insert(sdl->encoders,  &cur_type->encode, sizeof(encodePtr), NULL);
+
+               cur_type =*ptr;
+
+       } else if (name) {
                sdlTypePtr newType, *ptr;
 
                newType = malloc(sizeof(sdlType));
                memset(newType, 0, sizeof(sdlType));
-               newType->name = strdup(cur_type->name);
-               newType->namens = strdup(cur_type->namens);
+               newType->kind = XSD_TYPEKIND_COMPLEX;
+               newType->name = strdup(name->children->content);
+               newType->namens = strdup(ns->children->content);
 
                zend_hash_next_index_insert(sdl->types,  &newType, sizeof(sdlTypePtr), (void **)&ptr);
-               cur_type->encode = create_encoder(sdl, *ptr, (char *)(*ptr)->namens, (char *)(*ptr)->name);
-               cur_type =*ptr;
+
+               cur_type = (*ptr);
+               create_encoder(sdl, cur_type, ns->children->content, name->children->content);
+/*
+               if (cur_type->encode == NULL) {
+                       cur_type->encode = get_conversion(SOAP_ENC_OBJECT);
+               }
+*/
        } else {
                php_error(E_ERROR, "Error parsing schema (complexType has no 'name' attribute)");
+               return FALSE;
        }
 
        trav = compType->children;
@@ -1020,12 +1196,15 @@ static int schema_complexType(sdlPtr sdl, xmlAttrPtr tsn, xmlNodePtr compType, s
                                schema_group(sdl, tsn, trav, cur_type);
                                trav = trav->next;
                        } else if (node_is_equal(trav,"all")) {
+                               cur_type->kind = XSD_TYPEKIND_ALL;
                                schema_all(sdl, tsn, trav, cur_type);
                                trav = trav->next;
                        } else if (node_is_equal(trav,"choice")) {
+                               cur_type->kind = XSD_TYPEKIND_CHOICE;
                                schema_choice(sdl, tsn, trav, cur_type);
                                trav = trav->next;
                        } else if (node_is_equal(trav,"sequence")) {
+                               cur_type->kind = XSD_TYPEKIND_SEQUENCE;
                                schema_sequence(sdl, tsn, trav, cur_type);
                                trav = trav->next;
                        }
@@ -1078,7 +1257,7 @@ static int schema_complexType(sdlPtr sdl, xmlAttrPtr tsn, xmlNodePtr compType, s
 static int schema_element(sdlPtr sdl, xmlAttrPtr tsn, xmlNodePtr element, sdlTypePtr cur_type)
 {
        xmlNodePtr trav;
-       xmlAttrPtr attrs, curattr, name, ns, type;
+       xmlAttrPtr attrs, curattr, ns, name, type, ref = NULL;
 
        attrs = element->properties;
        ns = get_attribute(attrs, "targetNamespace");
@@ -1087,8 +1266,8 @@ static int schema_element(sdlPtr sdl, xmlAttrPtr tsn, xmlNodePtr element, sdlTyp
        }
 
        name = get_attribute(attrs, "name");
-       if (!name) {
-               name = get_attribute(attrs, "ref");
+       if (name == NULL) {
+               name = ref = get_attribute(attrs, "ref");
        }
 
        if (name) {
@@ -1099,8 +1278,30 @@ static int schema_element(sdlPtr sdl, xmlAttrPtr tsn, xmlNodePtr element, sdlTyp
                newType = malloc(sizeof(sdlType));
                memset(newType, 0, sizeof(sdlType));
 
-               newType->name = strdup(name->children->content);
-               newType->namens = strdup(tsn->children->content);
+               if (ref) {
+                       smart_str nscat = {0};
+                       char *type, *ns;
+                       xmlNsPtr nsptr;
+
+                       parse_namespace(ref->children->content, &type, &ns);
+                       nsptr = xmlSearchNs(element->doc, element, ns);
+                       if (nsptr != NULL) {
+                               smart_str_appends(&nscat, nsptr->href);
+                               smart_str_appendc(&nscat, ':');
+                               newType->namens = strdup(nsptr->href);
+                       }
+                       smart_str_appends(&nscat, type);
+                       newType->name = strdup(type);
+                       smart_str_0(&nscat);
+                       if (type) {efree(type);}
+                       if (ns) {efree(ns);}
+                       newType->ref = estrdup(nscat.c);
+                       smart_str_free(&nscat);
+               } else {
+                       newType->name = strdup(name->children->content);
+                       newType->namens = strdup(ns->children->content);
+               }
+
                newType->nillable = FALSE;
                newType->min_occurs = 1;
                newType->max_occurs = 1;
@@ -1122,9 +1323,6 @@ static int schema_element(sdlPtr sdl, xmlAttrPtr tsn, xmlNodePtr element, sdlTyp
                smart_str_0(&key);
                zend_hash_update(addHash, key.c, key.len + 1, &newType, sizeof(sdlTypePtr), (void **)&tmp);
                cur_type = (*tmp);
-/*
-               create_encoder(sdl, cur_type, ns->children->content, name->children->content);
-*/
                smart_str_free(&key);
        } else {
                php_error(E_ERROR, "Error parsing schema (element has no 'name' nor 'ref' attributes)");
@@ -1160,15 +1358,13 @@ static int schema_element(sdlPtr sdl, xmlAttrPtr tsn, xmlNodePtr element, sdlTyp
 
        /* type = QName */
        type = get_attribute(attrs, "type");
-/*
-       if (!curattr) {
-               curattr = name;
-       }
-*/
        if (type) {
                char *cptype, *str_ns;
                xmlNsPtr nsptr;
 
+               if (ref != NULL) {
+                       php_error(E_ERROR, "Error parsing schema (element have both 'ref' and 'type' attributes)");
+               }
                parse_namespace(type->children->content, &cptype, &str_ns);
                nsptr = xmlSearchNs(element->doc, element, str_ns);
                if (nsptr != NULL) {
@@ -1190,9 +1386,19 @@ static int schema_element(sdlPtr sdl, xmlAttrPtr tsn, xmlNodePtr element, sdlTyp
        }
        if (trav != NULL) {
                if (node_is_equal(trav,"simpleType")) {
+                       if (ref != NULL) {
+                               php_error(E_ERROR, "Error parsing schema (element have both 'ref' attribute and subtype)");
+                       } else if (type != NULL) {
+                               php_error(E_ERROR, "Error parsing schema (element have both 'type' attribute and subtype)");
+                       }
                        schema_simpleType(sdl, tsn, trav, cur_type);
                        trav = trav->next;
                } else if (node_is_equal(trav,"complexType")) {
+                       if (ref != NULL) {
+                               php_error(E_ERROR, "Error parsing schema (element have both 'ref' attribute and subtype)");
+                       } else if (type != NULL) {
+                               php_error(E_ERROR, "Error parsing schema (element have both 'type' attribute and subtype)");
+                       }
                        schema_complexType(sdl, tsn, trav, cur_type);
                        trav = trav->next;
                }
@@ -1373,3 +1579,47 @@ static int schema_attributeGroupRef(sdlPtr sdl, xmlAttrPtr tsn, xmlNodePtr attrG
        }
        return TRUE;
 }
+
+static void schema_type_fixup(sdlPtr sdl, sdlTypePtr type)
+{
+       sdlTypePtr *tmp;
+
+       if (type->ref != NULL) {
+               if (zend_hash_find(sdl->elements, type->ref, strlen(type->ref)+1, (void**)&tmp) == SUCCESS) {                   
+                       type->encode = (*tmp)->encode;
+                       /* TODO: nillable minOccurs, maxOccurs */
+               } else {
+                       php_error(E_ERROR, "Error parsing schema (unresolved element 'ref' attribute)");
+               }
+               efree(type->ref);
+               type->ref = NULL;
+       }
+       if (type->elements) {
+               zend_hash_internal_pointer_reset(type->elements);
+               while (zend_hash_get_current_data(type->elements,(void**)&tmp) == SUCCESS) {
+                       schema_type_fixup(sdl,*tmp);
+                       zend_hash_move_forward(type->elements);
+               }
+       }
+}
+
+int schema_pass2(sdlPtr sdl)
+{
+       sdlTypePtr *type;
+
+       if (sdl->elements) {
+               zend_hash_internal_pointer_reset(sdl->elements);
+               while (zend_hash_get_current_data(sdl->elements,(void**)&type) == SUCCESS) {
+                       schema_type_fixup(sdl,*type);
+                       zend_hash_move_forward(sdl->elements);
+               }
+       }
+       if (sdl->types) {
+               zend_hash_internal_pointer_reset(sdl->types);
+               while (zend_hash_get_current_data(sdl->types,(void**)&type) == SUCCESS) {
+                       schema_type_fixup(sdl,*type);
+                       zend_hash_move_forward(sdl->types);
+               }
+       }
+       return TRUE;
+}
index ed7a9d8e78c70a96845e6aae10f8e751a4206248..74994485dd3a9a4eab7914b8b9c1488a50ad5efe 100644 (file)
@@ -2,5 +2,6 @@
 #define PHP_SCHEMA_H
 
 int load_schema(sdlPtr sdl, xmlNodePtr schema);
+int schema_pass2(sdlPtr sdl);
 
 #endif
index 7f33427e8f1939651533bf654995b42da20784da..4d727b3e67095e973495d5aa75917ff8a43b7fb6 100644 (file)
@@ -28,7 +28,7 @@ encodePtr get_encoder_from_prefix(sdlPtr sdl, xmlNodePtr data, const char *type)
        return enc;
 }
 
-encodePtr get_encoder_from_element(sdlPtr sdl, xmlNodePtr node, const char *type)
+static encodePtr get_encoder_from_element(sdlPtr sdl, xmlNodePtr node, const char *type)
 {
        encodePtr enc = NULL;
        TSRMLS_FETCH();
@@ -161,6 +161,75 @@ encodePtr create_encoder(sdlPtr sdl, sdlTypePtr cur_type, const char *ns, const
        return enc;
 }
 
+static zval* to_zval_list(encodeType enc, xmlNodePtr data) {
+       zval *ret;
+       MAKE_STD_ZVAL(ret);
+       FIND_XML_NULL(data, ret);
+       if (data && data->children) {
+               if (data->children->type == XML_TEXT_NODE && data->children->next == NULL) {
+                       whiteSpace_collapse(data->children->content);
+                       ZVAL_STRING(ret, data->children->content, 1);
+               } else {
+                       php_error(E_ERROR,"Violation of encoding rules");
+               }
+       } else {
+               ZVAL_EMPTY_STRING(ret);
+       }
+       return ret;
+}
+
+static xmlNodePtr to_xml_list(encodeType enc, zval *data, int style) {
+       xmlNodePtr ret;
+
+       ret = xmlNewNode(NULL, "BOGUS");
+       FIND_ZVAL_NULL(data, ret, style);
+       if (Z_TYPE_P(data) == IS_ARRAY) {
+               zval **tmp;
+               smart_str list = {0};
+               HashTable *ht = Z_ARRVAL_P(data);
+
+               zend_hash_internal_pointer_reset(ht);
+               while (zend_hash_get_current_data(ht, (void**)&tmp) == SUCCESS) {
+                       if (list.len != 0) {
+                               smart_str_appendc(&list, ' ');
+                       }
+                       if (Z_TYPE_PP(tmp) == IS_STRING) {
+                               smart_str_appendl(&list, Z_STRVAL_PP(tmp), Z_STRLEN_PP(tmp));
+                       } else {
+                               zval copy = **tmp;
+                               zval_copy_ctor(&copy);
+                               convert_to_string(&copy);
+                               smart_str_appendl(&list, Z_STRVAL(copy), Z_STRLEN(copy));
+                               zval_dtor(&copy);
+                       }
+                       zend_hash_move_forward(ht);
+               }
+               smart_str_0(&list);
+               xmlNodeSetContentLen(ret, list.c, list.len);
+               smart_str_free(&list);
+       } else if (Z_TYPE_P(data) == IS_STRING) {
+               xmlNodeSetContentLen(ret, Z_STRVAL_P(data), Z_STRLEN_P(data));
+       } else {
+               zval tmp = *data;
+
+               zval_copy_ctor(&tmp);
+               convert_to_string(&tmp);
+               xmlNodeSetContentLen(ret, Z_STRVAL(tmp), Z_STRLEN(tmp));
+               zval_dtor(&tmp);
+       }
+       return ret;
+}
+
+static zval* to_zval_union(encodeType enc, xmlNodePtr data) {
+       /*FIXME*/
+       return to_zval_list(enc, data);
+}
+
+static xmlNodePtr to_xml_union(encodeType enc, zval *data, int style) {
+       /*FIXME*/
+       return to_xml_list(enc,data,style);
+}
+
 zval *sdl_guess_convert_zval(encodeType enc, xmlNodePtr data)
 {
        sdlTypePtr type;
@@ -209,6 +278,10 @@ zval *sdl_guess_convert_zval(encodeType enc, xmlNodePtr data)
                                return master_to_zval(get_conversion(UNKNOWN_TYPE), data);
                        }
                }
+       } else if (type->kind == XSD_TYPEKIND_LIST) {
+               return to_zval_list(enc, data);
+       } else if (type->kind == XSD_TYPEKIND_UNION) {
+               return to_zval_union(enc, data);
        } else if (type->elements) {
                return to_zval_object(enc, data);
        }       else {
@@ -258,12 +331,18 @@ xmlNodePtr sdl_guess_convert_xml(encodeType enc, zval *data, int style)
                                ret = master_to_xml(get_conversion(UNKNOWN_TYPE), data, style);
                        }
                }
-       }
-       else if (type->elements) {
+       } else if (type->kind == XSD_TYPEKIND_LIST) {
+               ret = to_xml_list(enc, data, style);
+       } else if (type->kind == XSD_TYPEKIND_UNION) {
+               ret = to_xml_union(enc, data, style);
+       } else if (type->elements) {
                ret = to_xml_object(enc, data, style);
        }       else {
                ret = guess_xml_convert(enc, data, style);
        }
+       if (style == SOAP_ENCODED) {
+               set_ns_and_type(ret, enc);
+       }
        return ret;
 }
 
@@ -428,6 +507,8 @@ static sdlPtr load_wsdl(char *struri)
 
        load_wsdl_ex(struri,&ctx, 0);
 
+       schema_pass2(ctx.root);
+
        n = zend_hash_num_elements(&ctx.services);
        if (n > 0) {
                zend_hash_internal_pointer_reset(&ctx.services);
@@ -688,6 +769,7 @@ static sdlPtr load_wsdl(char *struri)
                                                                sdlParamPtr param;
 
                                                                param = malloc(sizeof(sdlParam));
+                                                               memset(param,0,sizeof(sdlParam));
                                                                param->order = 0;
 
                                                                name = get_attribute(part->properties, "name");
@@ -783,6 +865,7 @@ static sdlPtr load_wsdl(char *struri)
                                                                xmlAttrPtr element, type, name;
 
                                                                param = malloc(sizeof(sdlParam));
+                                                               memset(param, 0, sizeof(sdlParam));
                                                                param->order = 0;
 
                                                                name = get_attribute(part->properties, "name");
index 06c0a8327442397570a1613f854ac760379038e0..ae6a90be6bd9caba9d557d8ebe72b43910e19887 100644 (file)
@@ -90,7 +90,19 @@ struct _sdlRestrictions {
        sdlRestrictionCharPtr pattern;
 };
 
+typedef enum _sdlTypeKind {
+       XSD_TYPEKIND_UNKNOWN,
+       XSD_TYPEKIND_SIMPLE,
+       XSD_TYPEKIND_COMPLEX,
+       XSD_TYPEKIND_LIST,
+       XSD_TYPEKIND_UNION,
+       XSD_TYPEKIND_ALL,
+       XSD_TYPEKIND_SEQUENCE,
+       XSD_TYPEKIND_CHOICE
+} sdlTypeKind;
+
 struct _sdlType {
+       sdlTypeKind kind;
        char *name;
        char *namens;
        int nillable;
@@ -100,6 +112,7 @@ struct _sdlType {
        HashTable *attributes;                          /* array of sdlAttributePtr */
        sdlRestrictionsPtr restrictions;
        encodePtr encode;
+       char *ref;
 };
 
 struct _sdlParam {
index b7b060fcd722cc00d1c1c92acefb12b26466e0e0..f69c131b776d1d9d2fbd696a33caac3a7681b341 100644 (file)
@@ -1200,7 +1200,6 @@ PHP_METHOD(soapserver, handle)
 
                zval_dtor(&function_name);
                xmlFreeDoc(doc_return);
-               efree(fn_name);
 
                php_write(buf, size TSRMLS_CC);
                xmlFree(buf);
@@ -1981,7 +1980,11 @@ static xmlDocPtr seralize_response_call(sdlFunctionPtr function, char *function_
                }
 
                if (function != NULL) {
-                       param_count = zend_hash_num_elements(function->responseParameters);
+                       if (function->responseParameters) {
+                               param_count = zend_hash_num_elements(function->responseParameters);
+                       } else {
+                         param_count = 0;
+                       }
                } else {
                  param_count = 1;
                }
@@ -2219,9 +2222,8 @@ static xmlNodePtr seralize_zval(zval *val, sdlParamPtr param, char *paramName, i
        if (param != NULL) {
                enc = param->encode;
        } else {
-               enc = get_conversion(val->type);
+               enc = get_conversion(val->type);
        }
-
        xmlParam = master_to_xml(enc, val, style);
        if (!strcmp(xmlParam->name, "BOGUS")) {
                xmlNodeSetName(xmlParam, paramName);