[xslt] str:replace implementation
- From: joel reed <joel reed ddiworld com>
- To: xslt gnome org
- Subject: [xslt] str:replace implementation
- Date: Mon, 08 Jan 2007 16:04:40 -0500
Please find attached an implementation of the exslt.org str:replace
function and 7 test cases.
Documentation on the function can be found here:
http://www.exslt.org/str/functions/replace/index.html
In that spec, I did not implement these last two sentences: "The longest
search strings are replaced first. If a search string is empty, then the
equivalently positioned replacement node is inserted between every
character in the string." I felt the added code complexity and
performance hit was not worth the impact at this time.
The other 11 sentences are implemented and add a useful capability to
libexslt (imho)!
Daniel and Bill: I hope you are both doing well. I'm not subscribed to
the xslt mailing list, and the mailman server seems to be busted with
reagards to new subscriptions.
jr
diff --git a/libexslt/strings.c b/libexslt/strings.c
index c867f9c..e624d2b 100644
--- a/libexslt/strings.c
+++ b/libexslt/strings.c
@@ -495,6 +495,115 @@ exsltStrConcatFunction (xmlXPathParserCo
}
/**
+ * 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 = xmlUTF8Strlen(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) {
+ const xmlChar *str, *searchStr, *replaceStr = NULL;
+ xmlNodeSetPtr replaceSet = NULL, searchSet;
+ 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);
+ return;
+ }
+ }
+
+ /* behavior driven by search argument from here on */
+ if (!xmlXPathStackIsNodeSet(ctxt)) {
+ searchStr = xmlXPathPopString(ctxt);
+ str = xmlXPathPopString(ctxt);
+
+ if (replaceStr == NULL) {
+ xmlXPathSetTypeError(ctxt);
+ return;
+ }
+
+ ret = exsltStrReplaceInternal(str, searchStr, replaceStr);
+ }
+ else {
+
+ searchSet = xmlXPathPopNodeSet(ctxt);
+ if (searchSet == NULL || xmlXPathCheckError(ctxt)) {
+ xmlXPathSetTypeError(ctxt);
+ return;
+ }
+
+ 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);
+ xmlFree(ret);
+
+ ret = retSwap;
+ }
+ }
+
+ xmlXPathReturnString(ctxt, ret);
+}
+
+/**
* exsltStrRegister:
*
* Registers the EXSLT - Strings module
@@ -523,4 +632,7 @@ exsltStrRegister (void) {
xsltRegisterExtModuleFunction ((const xmlChar *) "concat",
EXSLT_STRINGS_NAMESPACE,
exsltStrConcatFunction);
+ xsltRegisterExtModuleFunction ((const xmlChar *) "replace",
+ EXSLT_STRINGS_NAMESPACE,
+ exsltStrReplaceFunction);
}
diff --git a/tests/exslt/strings/replace.1.out b/tests/exslt/strings/replace.1.out
new file mode 100644
index 0000000..076d110
--- /dev/null
+++ b/tests/exslt/strings/replace.1.out
@@ -0,0 +1,22 @@
+<?xml version="1.0"?>
+<out>;
+ str:replace('a, simple, list', ', ', '-')
+ a-simple-list
+
+ str:replace('a, simple, list', 'a, ', 'the ')
+ the simple, list
+
+ str:replace('a, simple, list', 'list', 'array')
+ a, simple, array
+
+ str:replace('a, simple, list', 'i', 'I')
+ a, sImple, lIst
+
+ str:replace('a, simple, list', ', ', '')
+ asimplelist
+
+ str:replace('fee, fi, fo, fum', $x, $y)
+ tee, eye, billow, a longer string
+
+ str:replace('fee, fi, fo, fum', $x, 'j')
+ j, j, j, j</out>
diff --git a/tests/exslt/strings/replace.1.xml b/tests/exslt/strings/replace.1.xml
new file mode 100644
index 0000000..6371161
--- /dev/null
+++ b/tests/exslt/strings/replace.1.xml
@@ -0,0 +1,12 @@
+<doc>
+ <strings>
+ <x>fee</x>
+ <x>fi</x>
+ <x>fo</x>
+ <x>fum</x>
+ <y>tee</y>
+ <y>eye</y>
+ <y>billow</y>
+ <y>a longer string</y>
+ </strings>
+</doc>
diff --git a/tests/exslt/strings/replace.1.xsl b/tests/exslt/strings/replace.1.xsl
new file mode 100644
index 0000000..0c9e86c
--- /dev/null
+++ b/tests/exslt/strings/replace.1.xsl
@@ -0,0 +1,36 @@
+<?xml version="1.0"?>
+<xsl:stylesheet version="1.0"
+ xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+ xmlns:str="http://exslt.org/strings"
+ exclude-result-prefixes="str">
+
+<xsl:template match="/">
+ <xsl:variable name="x" select="doc/strings/x"/>
+ <xsl:variable name="y" select="doc/strings/y"/>
+
+<out>;
+ str:replace('a, simple, list', ', ', '-')
+ <xsl:copy-of select="str:replace('a, simple, list', ', ', '-')"/>
+
+ str:replace('a, simple, list', 'a, ', 'the ')
+ <xsl:copy-of select="str:replace('a, simple, list', 'a, ', 'the ')"/>
+
+ str:replace('a, simple, list', 'list', 'array')
+ <xsl:copy-of select="str:replace('a, simple, list', 'list', 'array')"/>
+
+ str:replace('a, simple, list', 'i', 'I')
+ <xsl:copy-of select="str:replace('a, simple, list', 'i', 'I')"/>
+
+ str:replace('a, simple, list', ', ', '')
+ <xsl:copy-of select="str:replace('a, simple, list', ', ', '')"/>
+
+ str:replace('fee, fi, fo, fum', $x, $y)
+ <xsl:copy-of select="str:replace('fee, fi, fo, fum', $x, $y)" />
+
+ str:replace('fee, fi, fo, fum', $x, 'j')
+ <xsl:copy-of select="str:replace('fee, fi, fo, fum', $x, 'j')" />
+
+</out>
+</xsl:template>
+
+</xsl:stylesheet>
begin:vcard
fn:Joel Reed
n:Reed;Joel
org:Development Dimensions International;E-Systems
adr;dom:;;1225 Washington Pike;Bridgeville;PA;15017
title:Manager, E-Products R&D
tel;work:412-257-3881
note;quoted-printable:Unleashing Executive Talent. Hiring & Promoting The Best.=0D=0A=
Developing Extraordinary Leaders. Discover how at www.ddiworld.com
x-mozilla-html:FALSE
version:2.1
end:vcard
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]