1 #include "libexslt/libexslt.h"
3 #if defined(WIN32) && !defined (__CYGWIN__)
4 #include <win32config.h>
9 #include <libxml/tree.h>
10 #include <libxml/xpath.h>
11 #include <libxml/xpathInternals.h>
12 #include <libxml/parser.h>
13 #include <libxml/encoding.h>
15 #include <libxslt/xsltconfig.h>
16 #include <libxslt/xsltutils.h>
17 #include <libxslt/xsltInternals.h>
18 #include <libxslt/extensions.h>
23 * exsltStrTokenizeFunction:
24 * @ctxt: an XPath parser context
25 * @nargs: the number of arguments
27 * Splits up a string and returns a node set of token elements, each
28 * containing one token from the string.
31 exsltStrTokenizeFunction (xmlXPathParserContextPtr ctxt, int nargs) {
32 xmlChar *str, *delimiters, *cur;
33 const xmlChar *token, *delimiter;
36 xmlXPathObjectPtr ret;
38 if ((nargs < 1) || (nargs > 2)) {
39 xmlXPathSetArityError (ctxt);
44 delimiters = xmlXPathPopString (ctxt);
45 if (xmlXPathCheckError(ctxt))
48 delimiters = xmlStrdup((const xmlChar *) "\t\r\n ");
50 if (delimiters == NULL)
53 str = xmlXPathPopString (ctxt);
54 if (xmlXPathCheckError(ctxt) || (str == NULL)) {
59 doc = xsltXPathGetTransformContext(ctxt)->document->doc;
60 ret = xmlXPathNewNodeSet (NULL);
64 * This is a hack: token elements are added as children of a
65 * fake element node. This is necessary to free them up
66 * correctly when freeing the node-set.
68 ret->user = (void *) xmlNewDocNode (doc, NULL,
69 (const xmlChar *) "fake", NULL);
70 if (ret->user == NULL)
74 for (cur = str, token = str; *cur != 0; cur++) {
75 for (delimiter = delimiters; *delimiter != 0; delimiter++) {
76 if (*cur == *delimiter) {
78 /* discard empty tokens */
82 node = xmlNewDocNode (doc, NULL,
83 (const xmlChar *) "token", token);
87 xmlAddChild ((xmlNodePtr) ret->user, node);
88 xmlXPathNodeSetAdd (ret->nodesetval, node);
93 node = xmlNewDocNode (doc, NULL, (const xmlChar *) "token", token);
94 xmlAddChild ((xmlNodePtr) ret->user, node);
95 xmlXPathNodeSetAdd (ret->nodesetval, node);
97 valuePush (ctxt, ret);
98 ret = NULL; /* hack to prevent freeing ret later */
102 xmlXPathFreeObject (ret);
105 if (delimiters != NULL)
110 * exsltStrPaddingFunction:
111 * @ctxt: an XPath parser context
112 * @nargs: the number of arguments
114 * Creates a padding string of a certain length.
117 exsltStrPaddingFunction (xmlXPathParserContextPtr ctxt, int nargs) {
118 int number, str_len = 0;
119 xmlChar *str = NULL, *ret = NULL, *tmp;
121 if ((nargs < 1) && (nargs > 2)) {
122 xmlXPathSetArityError(ctxt);
127 str = xmlXPathPopString(ctxt);
128 str_len = xmlUTF8Strlen(str);
131 if (str != NULL) xmlFree(str);
132 str = xmlStrdup((const xmlChar *) " ");
136 number = (int) xmlXPathPopNumber(ctxt);
139 xmlXPathReturnEmptyString(ctxt);
144 while (number >= str_len) {
145 ret = xmlStrncat(ret, str, str_len);
148 tmp = xmlUTF8Strndup (str, number);
149 ret = xmlStrcat(ret, tmp);
153 xmlXPathReturnString(ctxt, ret);
160 * exsltStrAlignFunction:
161 * @ctxt: an XPath parser context
162 * @nargs: the number of arguments
164 * Aligns a string within another string.
167 exsltStrAlignFunction (xmlXPathParserContextPtr ctxt, int nargs) {
168 xmlChar *str, *padding, *alignment, *ret;
169 int str_l, padding_l;
171 if ((nargs < 2) || (nargs > 3)) {
172 xmlXPathSetArityError(ctxt);
177 alignment = xmlXPathPopString(ctxt);
181 padding = xmlXPathPopString(ctxt);
182 str = xmlXPathPopString(ctxt);
184 str_l = xmlUTF8Strlen (str);
185 padding_l = xmlUTF8Strlen (padding);
187 if (str_l == padding_l) {
188 xmlXPathReturnString (ctxt, str);
194 if (str_l > padding_l) {
195 ret = xmlUTF8Strndup (str, padding_l);
197 if (xmlStrEqual(alignment, (const xmlChar *) "right")) {
198 ret = xmlUTF8Strndup (padding, padding_l - str_l);
199 ret = xmlStrcat (ret, str);
200 } else if (xmlStrEqual(alignment, (const xmlChar *) "center")) {
201 int left = (padding_l - str_l) / 2;
204 ret = xmlUTF8Strndup (padding, left);
205 ret = xmlStrcat (ret, str);
207 right_start = xmlUTF8Strsize (padding, left + str_l);
208 ret = xmlStrcat (ret, padding + right_start);
212 str_s = xmlStrlen (str);
213 ret = xmlStrdup (str);
214 ret = xmlStrcat (ret, padding + str_s);
218 xmlXPathReturnString (ctxt, ret);
226 * exsltStrConcatFunction:
227 * @ctxt: an XPath parser context
228 * @nargs: the number of arguments
230 * Takes a node set and returns the concatenation of the string values
231 * of the nodes in that node set. If the node set is empty, it
232 * returns an empty string.
235 exsltStrConcatFunction (xmlXPathParserContextPtr ctxt, int nargs) {
236 xmlXPathObjectPtr obj;
241 xmlXPathSetArityError(ctxt);
245 if (!xmlXPathStackIsNodeSet(ctxt)) {
246 xmlXPathSetTypeError(ctxt);
250 obj = valuePop (ctxt);
252 if (xmlXPathNodeSetIsEmpty(obj->nodesetval)) {
253 xmlXPathReturnEmptyString(ctxt);
257 for (i = 0; i < obj->nodesetval->nodeNr; i++) {
259 tmp = xmlXPathCastNodeToString(obj->nodesetval->nodeTab[i]);
261 ret = xmlStrcat (ret, tmp);
266 xmlXPathFreeObject (obj);
268 xmlXPathReturnString(ctxt, ret);
274 * Registers the EXSLT - Strings module
278 exsltStrRegister (void) {
279 xsltRegisterExtModuleFunction ((const xmlChar *) "tokenize",
280 EXSLT_STRINGS_NAMESPACE,
281 exsltStrTokenizeFunction);
282 xsltRegisterExtModuleFunction ((const xmlChar *) "padding",
283 EXSLT_STRINGS_NAMESPACE,
284 exsltStrPaddingFunction);
285 xsltRegisterExtModuleFunction ((const xmlChar *) "align",
286 EXSLT_STRINGS_NAMESPACE,
287 exsltStrAlignFunction);
288 xsltRegisterExtModuleFunction ((const xmlChar *) "concat",
289 EXSLT_STRINGS_NAMESPACE,
290 exsltStrConcatFunction);