📄 xml_to_soap.c
字号:
} /* Next, we begin to convert actual values. if no children, then must be a scalar value. */ if (!Q_Size(&el->children)) { if (!type && parent_array && parent_array->kids_type[0]) { type = parent_array->kids_type; } if (!type || !strcmp(type, TOKEN_STRING)) { XMLRPC_SetValueString(xCurrent, el->text.str, el->text.len); } else if (!strcmp(type, TOKEN_INT)) { XMLRPC_SetValueInt(xCurrent, atoi(el->text.str)); } else if (!strcmp(type, TOKEN_BOOLEAN)) { XMLRPC_SetValueBoolean(xCurrent, atoi(el->text.str)); } else if (!strcmp(type, TOKEN_DOUBLE) || !strcmp(type, TOKEN_FLOAT)) { XMLRPC_SetValueDouble(xCurrent, atof(el->text.str)); } else if (!strcmp(type, TOKEN_NULL)) { /* already an empty val. do nothing. */ } else if (!strcmp(type, TOKEN_DATETIME)) { XMLRPC_SetValueDateTime_ISO8601(xCurrent, el->text.str); } else if (!strcmp(type, TOKEN_BASE64)) { struct buffer_st buf; base64_decode(&buf, el->text.str, el->text.len); XMLRPC_SetValueBase64(xCurrent, buf.data, buf.offset); buffer_delete(&buf); } } /* Element has children, thus a vector, or "compound type" in soap-speak. */ else { struct array_info* ai = NULL; xml_element* iter = (xml_element*)Q_Head(&el->children); if (!type || !strcmp(type, TOKEN_STRUCT)) { XMLRPC_SetIsVector(xCurrent, xmlrpc_vector_struct); } else if (!strcmp(type, TOKEN_ARRAY) || arrayType != NULL) { /* determine magic associated with soap array type. this is passed down as we recurse, so our children have access to the info. */ ai = parse_array_type_info(arrayType); // alloc'ed ai free'd below. XMLRPC_SetIsVector(xCurrent, xmlrpc_vector_array); } else { /* mixed is probably closest thing we have to compound type. */ XMLRPC_SetIsVector(xCurrent, xmlrpc_vector_mixed); } /* Recurse, adding values as we go. Check for error during recursion and if found, bail. this short-circuits us out of the recursion. */ while ( iter && !XMLRPC_RequestGetError(request) ) { XMLRPC_VALUE xNext = NULL; /* top level elements don't actually represent values, so we just pass the current value along until we are deep enough. */ if ( depth <= 2 || (rtype == xmlrpc_request_response && depth <= 3) ) { xml_element_to_SOAP_REQUEST_worker(request, NULL, ai, xCurrent, iter, depth); } /* ready to do some actual de-serialization. create a new empty value and pass that along to be init'd, then add it to our current vector. */ else { xNext = XMLRPC_CreateValueEmpty(); xml_element_to_SOAP_REQUEST_worker(request, xCurrent, ai, xNext, iter, depth); XMLRPC_AddValueToVector(xCurrent, xNext); } iter = (xml_element*)Q_Next(&el->children); } /* cleanup */ if (ai) { free(ai); } } } return xCurrent;}/* Convert soap xml dom to XMLRPC_VALUE, sans request info. untested. */XMLRPC_VALUE xml_element_to_SOAP_VALUE(xml_element* el){ return xml_element_to_SOAP_REQUEST_worker(NULL, NULL, NULL, NULL, el, 0);}/* Convert soap xml dom to XMLRPC_REQUEST */XMLRPC_VALUE xml_element_to_SOAP_REQUEST(XMLRPC_REQUEST request, xml_element* el){ if (request) { return XMLRPC_RequestSetData(request, xml_element_to_SOAP_REQUEST_worker(request, NULL, NULL, NULL, el, 0)); } return NULL;}/* translates data structures to soap/xml. recursive */xml_element* SOAP_to_xml_element_worker(XMLRPC_REQUEST request, XMLRPC_VALUE node) {#define BUF_SIZE 128 xml_element* elem_val = NULL; if (node) { int bFreeNode = 0; /* sometimes we may need to free 'node' variable */ char buf[BUF_SIZE]; XMLRPC_VALUE_TYPE_EASY type = XMLRPC_GetValueTypeEasy(node); char* pName = NULL, *pAttrType = NULL; /* create our return value element */ elem_val = xml_elem_new(); switch (type) { case xmlrpc_type_struct: case xmlrpc_type_mixed: case xmlrpc_type_array: if (type == xmlrpc_type_array) { /* array's are _very_ special in soap. TODO: Should handle sparse/partial arrays here. */ /* determine soap array type. */ const char* type = get_array_soap_type(node); xml_element_attr* attr_array_type = NULL; /* specify array kids type and array size. */ snprintf(buf, sizeof(buf), "%s[%i]", type, XMLRPC_VectorSize(node)); attr_array_type = new_attr(TOKEN_ARRAY_TYPE, buf); Q_PushTail(&elem_val->attrs, attr_array_type); pAttrType = TOKEN_ARRAY; } /* check for fault, which is a rather special case. (can't these people design anything consistent/simple/elegant?) */ else if (type == xmlrpc_type_struct) { int fault_type = get_fault_type(node); if (fault_type) { if (fault_type == 1) { /* gen fault from xmlrpc style fault codes notice that we get a new node, which must be freed herein. */ node = gen_fault_xmlrpc(node, elem_val); bFreeNode = 1; } pName = TOKEN_FAULT; } } { /* recurse through sub-elements */ XMLRPC_VALUE xIter = XMLRPC_VectorRewind(node); while ( xIter ) { xml_element* next_el = SOAP_to_xml_element_worker(request, xIter); if (next_el) { Q_PushTail(&elem_val->children, next_el); } xIter = XMLRPC_VectorNext(node); } } break; /* handle scalar types */ case xmlrpc_type_empty: pAttrType = TOKEN_NULL; break; case xmlrpc_type_string: pAttrType = TOKEN_STRING; simplestring_addn(&elem_val->text, XMLRPC_GetValueString(node), XMLRPC_GetValueStringLen(node)); break; case xmlrpc_type_int: pAttrType = TOKEN_INT; snprintf(buf, BUF_SIZE, "%i", XMLRPC_GetValueInt(node)); simplestring_add(&elem_val->text, buf); break; case xmlrpc_type_boolean: pAttrType = TOKEN_BOOLEAN; snprintf(buf, BUF_SIZE, "%i", XMLRPC_GetValueBoolean(node)); simplestring_add(&elem_val->text, buf); break; case xmlrpc_type_double: pAttrType = TOKEN_DOUBLE; snprintf(buf, BUF_SIZE, "%f", XMLRPC_GetValueDouble(node)); simplestring_add(&elem_val->text, buf); break; case xmlrpc_type_datetime: { time_t tt = XMLRPC_GetValueDateTime(node); struct tm *tm = localtime (&tt); pAttrType = TOKEN_DATETIME; if(strftime (buf, BUF_SIZE, "%Y-%m-%dT%H:%M:%SZ", tm)) { simplestring_add(&elem_val->text, buf); } } break; case xmlrpc_type_base64: { struct buffer_st buf; pAttrType = TOKEN_BASE64; base64_encode(&buf, XMLRPC_GetValueBase64(node), XMLRPC_GetValueStringLen(node)); simplestring_addn(&elem_val->text, buf.data, buf.offset ); buffer_delete(&buf); } break; break; default: break; } /* determining element's name is a bit tricky, due to soap semantics. */ if (!pName) { /* if the value's type is known... */ if (pAttrType) { /* see if it has an id (key). If so, use that as name, and type as an attribute. */ pName = (char*)XMLRPC_GetValueID(node); if (pName) { Q_PushTail(&elem_val->attrs, new_attr(TOKEN_TYPE, pAttrType)); } /* otherwise, use the type as the name. */ else { pName = pAttrType; } } /* if the value's type is not known... (a rare case?) */ else { /* see if it has an id (key). otherwise, default to generic "item" */ pName = (char*)XMLRPC_GetValueID(node); if (!pName) { pName = "item"; } } } elem_val->name = strdup(pName); /* cleanup */ if (bFreeNode) { XMLRPC_CleanupValue(node); } } return elem_val;}/* convert XMLRPC_VALUE to soap xml dom. untested. */xml_element* SOAP_VALUE_to_xml_element(XMLRPC_VALUE node) { return SOAP_to_xml_element_worker(NULL, node);}/* convert XMLRPC_REQUEST to soap xml dom. */xml_element* SOAP_REQUEST_to_xml_element(XMLRPC_REQUEST request) { xml_element* root = xml_elem_new(); /* safety first. */ if (root) { xml_element* body = xml_elem_new(); root->name = strdup("SOAP-ENV:Envelope"); /* silly namespace stuff */ Q_PushTail(&root->attrs, new_attr("xmlns:SOAP-ENV", "http://schemas.xmlsoap.org/soap/envelope/")); Q_PushTail(&root->attrs, new_attr("xmlns:xsi", "http://www.w3.org/1999/XMLSchema-instance")); Q_PushTail(&root->attrs, new_attr("xmlns:xsd", "http://www.w3.org/1999/XMLSchema")); Q_PushTail(&root->attrs, new_attr("xmlns:SOAP-ENC", "http://schemas.xmlsoap.org/soap/encoding/")); Q_PushTail(&root->attrs, new_attr("xmlns:si", "http://soapinterop.org/xsd")); Q_PushTail(&root->attrs, new_attr("xmlns:ns6", "http://testuri.org")); Q_PushTail(&root->attrs, new_attr("SOAP-ENV:encodingStyle", "http://schemas.xmlsoap.org/soap/encoding/")); /* Q_PushHead(&root->attrs, new_attr("xmlns:ks", "http://kitchen.sink.org/soap/everything/under/sun")); JUST KIDDING!! :-) ----> ------------------------------------------------- */ if (body) { /* go ahead and serialize first... */ xml_element* el_serialized = SOAP_to_xml_element_worker(request, XMLRPC_RequestGetData(request)); /* check for fault, in which case, there is no intermediate element */ if (el_serialized && !strcmp(el_serialized->name, TOKEN_FAULT)) { Q_PushTail(&body->children, el_serialized); } /* usual case: not a fault. Add Response element in between. */ else { xml_element* rpc = xml_elem_new(); if (rpc) { const char* methodname = XMLRPC_RequestGetMethodName(request); XMLRPC_REQUEST_TYPE rtype = XMLRPC_RequestGetRequestType(request); /* if we are making a request, we want to use the methodname as is. */ if (rtype == xmlrpc_request_call) { if (methodname) { rpc->name = strdup(methodname); } } /* if it's a response, we append "Response". Also, given xmlrpc-epi API/architecture, it's likely that we don't have a methodname for the response, so we have to check that. */ else { char buf[128]; snprintf(buf, sizeof(buf), "%s%s", methodname ? methodname : "", "Response"); rpc->name = strdup(buf); } /* add serialized data to method call/response. add method call/response to body element */ if (rpc->name) { if(el_serialized) { if(Q_Size(&el_serialized->children) && rtype == xmlrpc_request_call) { xml_element* iter = (xml_element*)Q_Head(&el_serialized->children); while(iter) { Q_PushTail(&rpc->children, iter); iter = (xml_element*)Q_Next(&el_serialized->children); } xml_elem_free_non_recurse(el_serialized); } else { Q_PushTail(&rpc->children, el_serialized); } } Q_PushTail(&body->children, rpc); } else { /* no method name?! TODO: fault here...? */ } } } body->name = strdup("SOAP-ENV:Body"); Q_PushTail(&root->children, body); } } return root;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -