summaryrefslogtreecommitdiff
path: root/libexslt
diff options
context:
space:
mode:
authorWilliam M. Brack <wbrack@src.gnome.org>2007-01-11 03:13:13 +0000
committerWilliam M. Brack <wbrack@src.gnome.org>2007-01-11 03:13:13 +0000
commit40e7c29b35c975e4b7ff6275a9f8aaca24a4a86c (patch)
treece0476e8d46fa9bebf8b289617f3e9a521dae702 /libexslt
parent7581a7896fbf2d9216622b54265ed202692ea006 (diff)
downloadlibxslt-40e7c29b35c975e4b7ff6275a9f8aaca24a4a86c.tar.gz
libxslt-40e7c29b35c975e4b7ff6275a9f8aaca24a4a86c.tar.bz2
libxslt-40e7c29b35c975e4b7ff6275a9f8aaca24a4a86c.zip
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
Diffstat (limited to 'libexslt')
-rw-r--r--libexslt/strings.c140
1 files changed, 140 insertions, 0 deletions
diff --git a/libexslt/strings.c b/libexslt/strings.c
index c867f9cb..af7aa88a 100644
--- a/libexslt/strings.c
+++ b/libexslt/strings.c
@@ -495,6 +495,143 @@ exsltStrConcatFunction (xmlXPathParserContextPtr ctxt, int nargs) {
}
/**
+ * 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:
*
* Registers the EXSLT - Strings module
@@ -523,4 +660,7 @@ exsltStrRegister (void) {
xsltRegisterExtModuleFunction ((const xmlChar *) "concat",
EXSLT_STRINGS_NAMESPACE,
exsltStrConcatFunction);
+ xsltRegisterExtModuleFunction ((const xmlChar *) "replace",
+ EXSLT_STRINGS_NAMESPACE,
+ exsltStrReplaceFunction);
}