/** * exsltStrReturnString: * @ctxt: an XPath parser context * @str: a string * @len: length of string * * Returns a string as a node set. */ static int exsltStrReturnString(xmlXPathParserContextPtr ctxt, const xmlChar *str, int len) { xsltTransformContextPtr tctxt = xsltXPathGetTransformContext(ctxt); xmlDocPtr container; xmlNodePtr text_node; xmlXPathObjectPtr ret; container = xsltCreateRVT(tctxt); if (container == NULL) { xmlXPathSetError(ctxt, XPATH_MEMORY_ERROR); return(-1); } xsltRegisterLocalRVT(tctxt, container); text_node = xmlNewTextLen(str, len); if (text_node == NULL) { xmlXPathSetError(ctxt, XPATH_MEMORY_ERROR); return(-1); } xmlAddChild((xmlNodePtr) container, text_node); ret = xmlXPathNewNodeSet(text_node); if (ret == NULL) { xmlXPathSetError(ctxt, XPATH_MEMORY_ERROR); return(-1); } xsltExtensionInstructionResultRegister(tctxt, ret); valuePush(ctxt, ret); return(0); }
static void exsltNodeSetFunction (xmlXPathParserContextPtr ctxt, int nargs) { if (nargs != 1) { xmlXPathSetArityError(ctxt); return; } if (xmlXPathStackIsNodeSet (ctxt)) { xsltFunctionNodeSet (ctxt, nargs); return; } else { xmlDocPtr fragment; xsltTransformContextPtr tctxt = xsltXPathGetTransformContext(ctxt); xmlNodePtr txt; xmlChar *strval; xmlXPathObjectPtr obj; /* * SPEC EXSLT: * "You can also use this function to turn a string into a text * node, which is helpful if you want to pass a string to a * function that only accepts a node-set." */ fragment = xsltCreateRVT(tctxt); if (fragment == NULL) { xsltTransformError(tctxt, NULL, tctxt->inst, "exsltNodeSetFunction: Failed to create a tree fragment.\n"); tctxt->state = XSLT_STATE_STOPPED; return; } xsltRegisterLocalRVT(tctxt, fragment); strval = xmlXPathPopString (ctxt); txt = xmlNewDocText (fragment, strval); xmlAddChild((xmlNodePtr) fragment, txt); obj = xmlXPathNewNodeSet(txt); if (obj == NULL) { xsltTransformError(tctxt, NULL, tctxt->inst, "exsltNodeSetFunction: Failed to create a node set object.\n"); tctxt->state = XSLT_STATE_STOPPED; } else { /* * Mark it as a function result in order to avoid garbage * collecting of tree fragments */ xsltExtensionInstructionResultRegister(tctxt, obj); } if (strval != NULL) xmlFree (strval); valuePush (ctxt, obj); } }
/** * exsltStrTokenizeFunction: * @ctxt: an XPath parser context * @nargs: the number of arguments * * Splits up a string on the characters of the delimiter string and returns a * node set of token elements, each containing one token from the string. */ static void exsltStrTokenizeFunction(xmlXPathParserContextPtr ctxt, int nargs) { xsltTransformContextPtr tctxt; xmlChar *str, *delimiters, *cur; const xmlChar *token, *delimiter; xmlNodePtr node; xmlDocPtr container; xmlXPathObjectPtr ret = NULL; int clen; if ((nargs < 1) || (nargs > 2)) { xmlXPathSetArityError(ctxt); return; } if (nargs == 2) { delimiters = xmlXPathPopString(ctxt); if (xmlXPathCheckError(ctxt)) return; } else { delimiters = xmlStrdup((const xmlChar *) "\t\r\n "); } if (delimiters == NULL) return; str = xmlXPathPopString(ctxt); if (xmlXPathCheckError(ctxt) || (str == NULL)) { xmlFree(delimiters); return; } /* Return a result tree fragment */ tctxt = xsltXPathGetTransformContext(ctxt); if (tctxt == NULL) { xsltTransformError(xsltXPathGetTransformContext(ctxt), NULL, NULL, "exslt:tokenize : internal error tctxt == NULL\n"); goto fail; } container = xsltCreateRVT(tctxt); if (container != NULL) { xsltRegisterLocalRVT(tctxt, container); ret = xmlXPathNewNodeSet(NULL); if (ret != NULL) { for (cur = str, token = str; *cur != 0; cur += clen) { clen = xmlUTF8Size(cur); if (*delimiters == 0) { /* empty string case */ xmlChar ctmp; ctmp = *(cur+clen); *(cur+clen) = 0; node = xmlNewDocRawNode(container, NULL, (const xmlChar *) "token", cur); xmlAddChild((xmlNodePtr) container, node); xmlXPathNodeSetAddUnique(ret->nodesetval, node); *(cur+clen) = ctmp; /* restore the changed byte */ token = cur + clen; } else for (delimiter = delimiters; *delimiter != 0; delimiter += xmlUTF8Size(delimiter)) { if (!xmlUTF8Charcmp(cur, delimiter)) { if (cur == token) { /* discard empty tokens */ token = cur + clen; break; } *cur = 0; /* terminate the token */ node = xmlNewDocRawNode(container, NULL, (const xmlChar *) "token", token); xmlAddChild((xmlNodePtr) container, node); xmlXPathNodeSetAddUnique(ret->nodesetval, node); *cur = *delimiter; /* restore the changed byte */ token = cur + clen; break; } } } if (token != cur) { node = xmlNewDocRawNode(container, NULL, (const xmlChar *) "token", token); xmlAddChild((xmlNodePtr) container, node); xmlXPathNodeSetAddUnique(ret->nodesetval, node); } /* * Mark it as a function result in order to avoid garbage * collecting of tree fragments */ xsltExtensionInstructionResultRegister(tctxt, ret); } } fail: if (str != NULL) xmlFree(str); if (delimiters != NULL) xmlFree(delimiters); if (ret != NULL) valuePush(ctxt, ret); else valuePush(ctxt, xmlXPathNewNodeSet(NULL)); }
/** * exsltStrSplitFunction: * @ctxt: an XPath parser context * @nargs: the number of arguments * * Splits up a string on a delimiting string and returns a node set of token * elements, each containing one token from the string. */ static void exsltStrSplitFunction(xmlXPathParserContextPtr ctxt, int nargs) { xsltTransformContextPtr tctxt; xmlChar *str, *delimiter, *cur; const xmlChar *token; xmlNodePtr node; xmlDocPtr container; xmlXPathObjectPtr ret = NULL; int delimiterLength; if ((nargs < 1) || (nargs > 2)) { xmlXPathSetArityError(ctxt); return; } if (nargs == 2) { delimiter = xmlXPathPopString(ctxt); if (xmlXPathCheckError(ctxt)) return; } else { delimiter = xmlStrdup((const xmlChar *) " "); } if (delimiter == NULL) return; delimiterLength = xmlStrlen (delimiter); str = xmlXPathPopString(ctxt); if (xmlXPathCheckError(ctxt) || (str == NULL)) { xmlFree(delimiter); return; } /* Return a result tree fragment */ tctxt = xsltXPathGetTransformContext(ctxt); if (tctxt == NULL) { xsltTransformError(xsltXPathGetTransformContext(ctxt), NULL, NULL, "exslt:tokenize : internal error tctxt == NULL\n"); goto fail; } /* * OPTIMIZE TODO: We are creating an xmlDoc for every split! */ container = xsltCreateRVT(tctxt); if (container != NULL) { xsltRegisterLocalRVT(tctxt, container); ret = xmlXPathNewNodeSet(NULL); if (ret != NULL) { for (cur = str, token = str; *cur != 0; cur++) { if (delimiterLength == 0) { if (cur != token) { xmlChar tmp = *cur; *cur = 0; node = xmlNewDocRawNode(container, NULL, (const xmlChar *) "token", token); xmlAddChild((xmlNodePtr) container, node); xmlXPathNodeSetAddUnique(ret->nodesetval, node); *cur = tmp; token++; } } else if (!xmlStrncasecmp(cur, delimiter, delimiterLength)) { if (cur == token) { /* discard empty tokens */ cur = cur + delimiterLength - 1; token = cur + 1; continue; } *cur = 0; node = xmlNewDocRawNode(container, NULL, (const xmlChar *) "token", token); xmlAddChild((xmlNodePtr) container, node); xmlXPathNodeSetAddUnique(ret->nodesetval, node); *cur = *delimiter; cur = cur + delimiterLength - 1; token = cur + 1; } } if (token != cur) { node = xmlNewDocRawNode(container, NULL, (const xmlChar *) "token", token); xmlAddChild((xmlNodePtr) container, node); xmlXPathNodeSetAddUnique(ret->nodesetval, node); } /* * Mark it as a function result in order to avoid garbage * collecting of tree fragments */ xsltExtensionInstructionResultRegister(tctxt, ret); } } fail: if (str != NULL) xmlFree(str); if (delimiter != NULL) xmlFree(delimiter); if (ret != NULL) valuePush(ctxt, ret); else valuePush(ctxt, xmlXPathNewNodeSet(NULL)); }
static lx_nodeset_t * js_rpc_get_reply (xmlXPathParserContext *ctxt, js_session_t *jsp) { lx_document_t *docp = js_rpc_get_document(jsp); if (docp == NULL) goto fail; lx_node_t *nop = lx_document_root(docp); if (nop == NULL) { jsio_trace("jsio: could not find document root"); goto fail; } if (trace_flag_is_set(trace_file, CS_TRC_RPC)) lx_trace_node(nop, "results of rpc"); if (!streq(xmlNodeName(nop), XMLRPC_APINAME)) { jsio_trace("jsio: could not find api tag"); goto fail; } /* * Create a Result Value Tree container, and register it with RVT garbage * collector. */ xsltTransformContextPtr tctxt = xsltXPathGetTransformContext(ctxt); xmlDocPtr container = xsltCreateRVT(tctxt); xsltRegisterLocalRVT(tctxt, container); for (nop = lx_node_children(nop); nop; nop = lx_node_next(nop)) { if (streq(xmlNodeName(nop), XMLRPC_REPLY)) { lx_node_t *cop, *newp; lx_nodeset_t *setp = xmlXPathNodeSetCreate(NULL); if (setp == NULL) { jsio_trace("jsio: could not allocate set"); goto fail; } ext_jcs_fix_namespaces(nop); for (cop = lx_node_children(nop); cop; cop = lx_node_next(cop)) { if (cop->type == XML_TEXT_NODE && streq((const char *) cop->content, "\n")) continue; newp = xmlCopyNode(cop, 1); xmlXPathNodeSetAdd(setp, newp); /* * Attach the return nodes with RVT container, so that the * nodes will be freed when the container is freed. */ xmlAddChild((lx_node_t *) container, newp); } lx_document_free(docp); return setp; } } fail: jsio_trace("invalid reply to rpc"); if (docp) lx_document_free(docp); return NULL; }
static void exsltDynMapFunction(xmlXPathParserContextPtr ctxt, int nargs) { xmlChar *str = NULL; xmlNodeSetPtr nodeset = NULL; xsltTransformContextPtr tctxt; xmlXPathCompExprPtr comp = NULL; xmlXPathObjectPtr ret = NULL; xmlDocPtr oldDoc, container = NULL; xmlNodePtr oldNode; int oldContextSize; int oldProximityPosition; int i, j; if (nargs != 2) { xmlXPathSetArityError(ctxt); return; } str = xmlXPathPopString(ctxt); if (xmlXPathCheckError(ctxt)) { xmlXPathSetTypeError(ctxt); return; } nodeset = xmlXPathPopNodeSet(ctxt); if (xmlXPathCheckError(ctxt)) { xmlXPathSetTypeError(ctxt); return; } if (str == NULL || !xmlStrlen(str) || !(comp = xmlXPathCompile(str))) { if (nodeset != NULL) xmlXPathFreeNodeSet(nodeset); if (str != NULL) xmlFree(str); valuePush(ctxt, xmlXPathNewNodeSet(NULL)); return; } ret = xmlXPathNewNodeSet(NULL); if (ret == NULL) { xsltGenericError(xsltGenericErrorContext, "exsltDynMapFunction: ret == NULL\n"); goto cleanup; } oldDoc = ctxt->context->doc; oldNode = ctxt->context->node; oldContextSize = ctxt->context->contextSize; oldProximityPosition = ctxt->context->proximityPosition; tctxt = xsltXPathGetTransformContext(ctxt); if (tctxt == NULL) { xsltTransformError(xsltXPathGetTransformContext(ctxt), NULL, NULL, "dyn:map : internal error tctxt == NULL\n"); goto cleanup; } container = xsltCreateRVT(tctxt); if (container == NULL) { xsltTransformError(tctxt, NULL, NULL, "dyn:map : internal error container == NULL\n"); goto cleanup; } xsltRegisterLocalRVT(tctxt, container); if (nodeset && nodeset->nodeNr > 0) { xmlXPathNodeSetSort(nodeset); ctxt->context->contextSize = nodeset->nodeNr; ctxt->context->proximityPosition = 0; for (i = 0; i < nodeset->nodeNr; i++) { xmlXPathObjectPtr subResult = NULL; ctxt->context->proximityPosition++; ctxt->context->node = nodeset->nodeTab[i]; ctxt->context->doc = nodeset->nodeTab[i]->doc; subResult = xmlXPathCompiledEval(comp, ctxt->context); if (subResult != NULL) { switch (subResult->type) { case XPATH_NODESET: if (subResult->nodesetval != NULL) for (j = 0; j < subResult->nodesetval->nodeNr; j++) xmlXPathNodeSetAdd(ret->nodesetval, subResult->nodesetval-> nodeTab[j]); break; case XPATH_BOOLEAN: if (container != NULL) { xmlNodePtr cur = xmlNewChild((xmlNodePtr) container, NULL, BAD_CAST "boolean", BAD_CAST (subResult-> boolval ? "true" : "")); if (cur != NULL) { cur->ns = xmlNewNs(cur, BAD_CAST "http://exslt.org/common", BAD_CAST "exsl"); xmlXPathNodeSetAddUnique(ret->nodesetval, cur); } xsltExtensionInstructionResultRegister(tctxt, ret); } break; case XPATH_NUMBER: if (container != NULL) { xmlChar *val = xmlXPathCastNumberToString(subResult-> floatval); xmlNodePtr cur = xmlNewChild((xmlNodePtr) container, NULL, BAD_CAST "number", val); if (val != NULL) xmlFree(val); if (cur != NULL) { cur->ns = xmlNewNs(cur, BAD_CAST "http://exslt.org/common", BAD_CAST "exsl"); xmlXPathNodeSetAddUnique(ret->nodesetval, cur); } xsltExtensionInstructionResultRegister(tctxt, ret); } break; case XPATH_STRING: if (container != NULL) { xmlNodePtr cur = xmlNewChild((xmlNodePtr) container, NULL, BAD_CAST "string", subResult->stringval); if (cur != NULL) { cur->ns = xmlNewNs(cur, BAD_CAST "http://exslt.org/common", BAD_CAST "exsl"); xmlXPathNodeSetAddUnique(ret->nodesetval, cur); } xsltExtensionInstructionResultRegister(tctxt, ret); } break; default: break; } xmlXPathFreeObject(subResult); } } } ctxt->context->doc = oldDoc; ctxt->context->node = oldNode; ctxt->context->contextSize = oldContextSize; ctxt->context->proximityPosition = oldProximityPosition; cleanup: if (comp != NULL) xmlXPathFreeCompExpr(comp); if (nodeset != NULL) xmlXPathFreeNodeSet(nodeset); if (str != NULL) xmlFree(str); valuePush(ctxt, ret); return; }