From 40e7c29b35c975e4b7ff6275a9f8aaca24a4a86c Mon Sep 17 00:00:00 2001 From: "William M. Brack" Date: Thu, 11 Jan 2007 03:13:13 +0000 Subject: added new function replace from Joel Reed. added new test case for above. * libexslt/strings.c: added new function replace from Joel Reed. * tests/exslt/Makefile.am, replace.1.xml, replace.1.xsl, replace.1.out: added new test case for above. * libxslt.spec.in: trivial change from Gnome to GNOME * configure.in: trivial change for flags on my compilations * libxslt/documents.c, libxslt/documents.h, libxslt/keys.c, libxslt/keys.h, libxslt/variables.c, libxslt/templates.c, libxslt/transform.c, libxslt/variables.c, libxslt/xslt.c, libxslt/xsltutils.c: fixed some documentation/comments and compilation warnings - no change to logic. * re-generated the documentation. svn path=/trunk/; revision=1413 --- libexslt/strings.c | 140 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 140 insertions(+) (limited to 'libexslt') diff --git a/libexslt/strings.c b/libexslt/strings.c index c867f9cb..af7aa88a 100644 --- a/libexslt/strings.c +++ b/libexslt/strings.c @@ -494,6 +494,143 @@ exsltStrConcatFunction (xmlXPathParserContextPtr ctxt, int nargs) { xmlXPathReturnString(ctxt, ret); } +/** + * exsltStrReplaceInternal: + * @str: string to modify + * @searchStr: string to find + * @replaceStr: string to replace occurrences of searchStr + * + * Search and replace string function used by exsltStrReplaceFunction + */ +static xmlChar* +exsltStrReplaceInternal(const xmlChar* str, const xmlChar* searchStr, + const xmlChar* replaceStr) +{ + const xmlChar *curr, *next; + xmlChar *ret = NULL; + int searchStrSize; + + curr = str; + searchStrSize = xmlStrlen(searchStr); + + do { + next = xmlStrstr(curr, searchStr); + if (next == NULL) { + ret = xmlStrcat (ret, curr); + break; + } + + ret = xmlStrncat (ret, curr, next - curr); + ret = xmlStrcat (ret, replaceStr); + curr = next + searchStrSize; + } while (*curr != 0); + + return ret; +} +/** + * exsltStrReplaceFunction: + * @ctxt: an XPath parser context + * @nargs: the number of arguments + * + * Takes a string, and two node sets and returns the string with all strings in + * the first node set replaced by all strings in the second node set. + */ +static void +exsltStrReplaceFunction (xmlXPathParserContextPtr ctxt, int nargs) { + xmlChar *str = NULL, *searchStr = NULL, *replaceStr = NULL; + xmlNodeSetPtr replaceSet = NULL, searchSet = NULL; + xmlChar *ret = NULL, *retSwap = NULL; + int i; + + if (nargs != 3) { + xmlXPathSetArityError(ctxt); + return; + } + + /* pull out replace argument */ + if (!xmlXPathStackIsNodeSet(ctxt)) { + replaceStr = xmlXPathPopString(ctxt); + } + else { + replaceSet = xmlXPathPopNodeSet(ctxt); + if (xmlXPathCheckError(ctxt)) { + xmlXPathSetTypeError(ctxt); + goto fail; + } + } + + /* behavior driven by search argument from here on */ + if (!xmlXPathStackIsNodeSet(ctxt)) { + searchStr = xmlXPathPopString(ctxt); + str = xmlXPathPopString(ctxt); + + if (replaceStr == NULL) { + xmlXPathSetTypeError(ctxt); + goto fail; + } + + ret = exsltStrReplaceInternal(str, searchStr, replaceStr); + } + else { + searchSet = xmlXPathPopNodeSet(ctxt); + if (searchSet == NULL || xmlXPathCheckError(ctxt)) { + xmlXPathSetTypeError(ctxt); + goto fail; + } + + str = xmlXPathPopString(ctxt); + ret = xmlStrdup(str); + + for (i = 0; i < searchSet->nodeNr; i++) { + + searchStr = xmlXPathCastNodeToString(searchSet->nodeTab[i]); + + if (replaceSet != NULL) { + replaceStr = NULL; + if (i <= replaceSet->nodeNr) { + replaceStr = xmlXPathCastNodeToString(replaceSet->nodeTab[i]); + } + + retSwap = exsltStrReplaceInternal(ret, searchStr, replaceStr); + + if (replaceStr != NULL) { + xmlFree(replaceStr); + replaceStr = NULL; + } + } + else { + retSwap = exsltStrReplaceInternal(ret, searchStr, replaceStr); + } + + xmlFree(ret); + if (searchStr != NULL) { + xmlFree(searchStr); + searchStr = NULL; + } + + ret = retSwap; + } + + if (replaceSet != NULL) + xmlXPathFreeNodeSet(replaceSet); + + if (searchSet != NULL) + xmlXPathFreeNodeSet(searchSet); + } + + xmlXPathReturnString(ctxt, ret); + + fail: + if (replaceStr != NULL) + xmlFree(replaceStr); + + if (searchStr != NULL) + xmlFree(searchStr); + + if (str != NULL) + xmlFree(str); +} + /** * exsltStrRegister: * @@ -523,4 +660,7 @@ exsltStrRegister (void) { xsltRegisterExtModuleFunction ((const xmlChar *) "concat", EXSLT_STRINGS_NAMESPACE, exsltStrConcatFunction); + xsltRegisterExtModuleFunction ((const xmlChar *) "replace", + EXSLT_STRINGS_NAMESPACE, + exsltStrReplaceFunction); } -- cgit v1.2.3