ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

attrvt.c
Go to the documentation of this file.
00001 /*
00002  * attrvt.c: Implementation of the XSL Transformation 1.0 engine
00003  *           attribute value template handling part.
00004  *
00005  * References:
00006  *   http://www.w3.org/TR/1999/REC-xslt-19991116
00007  *
00008  *   Michael Kay "XSLT Programmer's Reference" pp 637-643
00009  *   Writing Multiple Output Files
00010  *
00011  * See Copyright for the status of this software.
00012  *
00013  * daniel@veillard.com
00014  */
00015 
00016 #define IN_LIBXSLT
00017 #include "libxslt.h"
00018 
00019 #include <string.h>
00020 
00021 #include <libxml/xmlmemory.h>
00022 #include <libxml/tree.h>
00023 #include <libxml/xpath.h>
00024 #include <libxml/xpathInternals.h>
00025 #include "xslt.h"
00026 #include "xsltutils.h"
00027 #include "xsltInternals.h"
00028 #include "templates.h"
00029 
00030 #ifdef WITH_XSLT_DEBUG
00031 #define WITH_XSLT_DEBUG_AVT
00032 #endif
00033 
00034 #define MAX_AVT_SEG 10
00035 
00036 typedef struct _xsltAttrVT xsltAttrVT;
00037 typedef xsltAttrVT *xsltAttrVTPtr;
00038 struct _xsltAttrVT {
00039     struct _xsltAttrVT *next; /* next xsltAttrVT */
00040     int nb_seg;     /* Number of segments */
00041     int max_seg;    /* max capacity before re-alloc needed */
00042     int strstart;   /* is the start a string */
00043     /*
00044      * the namespaces in scope
00045      */
00046     xmlNsPtr *nsList;
00047     int nsNr;
00048     /*
00049      * the content is an alternate of string and xmlXPathCompExprPtr
00050      */
00051     void *segments[MAX_AVT_SEG];
00052 };
00053 
00062 static xsltAttrVTPtr
00063 xsltNewAttrVT(xsltStylesheetPtr style) {
00064     xsltAttrVTPtr cur;
00065 
00066     cur = (xsltAttrVTPtr) xmlMalloc(sizeof(xsltAttrVT));
00067     if (cur == NULL) {
00068     xsltTransformError(NULL, style, NULL,
00069         "xsltNewAttrVTPtr : malloc failed\n");
00070     if (style != NULL) style->errors++;
00071     return(NULL);
00072     }
00073     memset(cur, 0, sizeof(xsltAttrVT));
00074 
00075     cur->nb_seg = 0;
00076     cur->max_seg = MAX_AVT_SEG;
00077     cur->strstart = 0;
00078     cur->next = style->attVTs;
00079     /*
00080      * Note: this pointer may be changed by a re-alloc within xsltCompileAttr,
00081      * so that code may change the stylesheet pointer also!
00082      */
00083     style->attVTs = (xsltAttrVTPtr) cur;
00084 
00085     return(cur);
00086 }
00087 
00094 static void
00095 xsltFreeAttrVT(xsltAttrVTPtr avt) {
00096     int i;
00097 
00098     if (avt == NULL) return;
00099 
00100     if (avt->strstart == 1) {
00101     for (i = 0;i < avt->nb_seg; i += 2)
00102         if (avt->segments[i] != NULL)
00103         xmlFree((xmlChar *) avt->segments[i]);
00104     for (i = 1;i < avt->nb_seg; i += 2)
00105         xmlXPathFreeCompExpr((xmlXPathCompExprPtr) avt->segments[i]);
00106     } else {
00107     for (i = 0;i < avt->nb_seg; i += 2)
00108         xmlXPathFreeCompExpr((xmlXPathCompExprPtr) avt->segments[i]);
00109     for (i = 1;i < avt->nb_seg; i += 2)
00110         if (avt->segments[i] != NULL)
00111         xmlFree((xmlChar *) avt->segments[i]);
00112     }
00113     if (avt->nsList != NULL)
00114         xmlFree(avt->nsList);
00115     xmlFree(avt);
00116 }
00117 
00124 void
00125 xsltFreeAVTList(void *avt) {
00126     xsltAttrVTPtr cur = (xsltAttrVTPtr) avt, next;
00127 
00128     while (cur != NULL) {
00129         next = cur->next;
00130     xsltFreeAttrVT(cur);
00131     cur = next;
00132     }
00133 }
00146 static xsltAttrVTPtr
00147 xsltSetAttrVTsegment(xsltAttrVTPtr avt, void *val) {
00148     if (avt->nb_seg >= avt->max_seg) {
00149     avt = (xsltAttrVTPtr) xmlRealloc(avt, sizeof(xsltAttrVT) +
00150                 avt->max_seg * sizeof(void *));
00151     if (avt == NULL) {
00152         return NULL;
00153     }
00154     memset(&avt->segments[avt->nb_seg], 0, MAX_AVT_SEG*sizeof(void *));
00155     avt->max_seg += MAX_AVT_SEG;
00156     }
00157     avt->segments[avt->nb_seg++] = val;
00158     return avt;
00159 }
00160 
00170 void
00171 xsltCompileAttr(xsltStylesheetPtr style, xmlAttrPtr attr) {
00172     const xmlChar *str;
00173     const xmlChar *cur;
00174     xmlChar *ret = NULL;
00175     xmlChar *expr = NULL;
00176     xsltAttrVTPtr avt;
00177     int i = 0, lastavt = 0;
00178 
00179     if ((style == NULL) || (attr == NULL) || (attr->children == NULL))
00180         return;
00181     if ((attr->children->type != XML_TEXT_NODE) || 
00182         (attr->children->next != NULL)) {
00183         xsltTransformError(NULL, style, attr->parent,
00184         "Attribute '%s': The content is expected to be a single text "
00185         "node when compiling an AVT.\n", attr->name);
00186     style->errors++;
00187     return;
00188     }
00189     str = attr->children->content;
00190     if ((xmlStrchr(str, '{') == NULL) &&
00191         (xmlStrchr(str, '}') == NULL)) return;
00192 
00193 #ifdef WITH_XSLT_DEBUG_AVT
00194     xsltGenericDebug(xsltGenericDebugContext,
00195             "Found AVT %s: %s\n", attr->name, str);
00196 #endif
00197     if (attr->psvi != NULL) {
00198 #ifdef WITH_XSLT_DEBUG_AVT
00199     xsltGenericDebug(xsltGenericDebugContext,
00200             "AVT %s: already compiled\n", attr->name);
00201 #endif
00202         return;
00203     }
00204     /*
00205     * Create a new AVT object.
00206     */
00207     avt = xsltNewAttrVT(style);
00208     if (avt == NULL)
00209     return;
00210     attr->psvi = avt;
00211 
00212     avt->nsList = xmlGetNsList(attr->doc, attr->parent);
00213     if (avt->nsList != NULL) {
00214     while (avt->nsList[i] != NULL)
00215         i++;
00216     }
00217     avt->nsNr = i;
00218 
00219     cur = str;
00220     while (*cur != 0) {
00221     if (*cur == '{') {
00222         if (*(cur+1) == '{') {  /* escaped '{' */
00223             cur++;
00224         ret = xmlStrncat(ret, str, cur - str);
00225         cur++;
00226         str = cur;
00227         continue;
00228         }
00229         if (*(cur+1) == '}') {  /* skip empty AVT */
00230         ret = xmlStrncat(ret, str, cur - str);
00231             cur += 2;
00232         str = cur;
00233         continue;
00234         }
00235         if ((ret != NULL) || (cur - str > 0)) {
00236         ret = xmlStrncat(ret, str, cur - str);
00237         str = cur;
00238         if (avt->nb_seg == 0)
00239             avt->strstart = 1;
00240         if ((avt = xsltSetAttrVTsegment(avt, (void *) ret)) == NULL)
00241             goto error;
00242         ret = NULL;
00243         lastavt = 0;
00244         }
00245 
00246         cur++;
00247         while ((*cur != 0) && (*cur != '}')) {
00248         /* Need to check for literal (bug539741) */
00249         if ((*cur == '\'') || (*cur == '"')) {
00250             char delim = *(cur++);
00251             while ((*cur != 0) && (*cur != delim)) 
00252             cur++;
00253             if (*cur != 0)
00254             cur++;  /* skip the ending delimiter */
00255         } else
00256             cur++;
00257         }
00258         if (*cur == 0) {
00259             xsltTransformError(NULL, style, attr->parent,
00260              "Attribute '%s': The AVT has an unmatched '{'.\n",
00261              attr->name);
00262         style->errors++;
00263         goto error;
00264         }
00265         str++;
00266         expr = xmlStrndup(str, cur - str);
00267         if (expr == NULL) {
00268         /*
00269         * TODO: What needs to be done here?
00270         */
00271             XSLT_TODO
00272         goto error;
00273         } else {
00274         xmlXPathCompExprPtr comp;
00275 
00276         comp = xsltXPathCompile(style, expr);
00277         if (comp == NULL) {
00278             xsltTransformError(NULL, style, attr->parent,
00279              "Attribute '%s': Failed to compile the expression "
00280              "'%s' in the AVT.\n", attr->name, expr);
00281             style->errors++;
00282             goto error;
00283         }
00284         if (avt->nb_seg == 0)
00285             avt->strstart = 0;
00286         if (lastavt == 1) {
00287             if ((avt = xsltSetAttrVTsegment(avt, NULL)) == NULL)
00288                 goto error;
00289         }
00290         if ((avt = xsltSetAttrVTsegment(avt, (void *) comp)) == NULL)
00291             goto error;
00292         lastavt = 1;
00293         xmlFree(expr);
00294         expr = NULL;
00295         }
00296         cur++;
00297         str = cur;
00298     } else if (*cur == '}') {
00299         cur++;
00300         if (*cur == '}') {  /* escaped '}' */
00301         ret = xmlStrncat(ret, str, cur - str);
00302         cur++;
00303         str = cur;
00304         continue;
00305         } else {
00306             xsltTransformError(NULL, style, attr->parent,
00307              "Attribute '%s': The AVT has an unmatched '}'.\n",
00308              attr->name);
00309         goto error;
00310         }
00311     } else
00312         cur++;
00313     }
00314     if ((ret != NULL) || (cur - str > 0)) {
00315     ret = xmlStrncat(ret, str, cur - str);
00316     str = cur;
00317     if (avt->nb_seg == 0)
00318         avt->strstart = 1;
00319     if ((avt = xsltSetAttrVTsegment(avt, (void *) ret)) == NULL)
00320         goto error;
00321     ret = NULL;
00322     }
00323 
00324 error:
00325     if (avt == NULL) {
00326         xsltTransformError(NULL, style, attr->parent,
00327         "xsltCompileAttr: malloc problem\n");
00328     } else {
00329         if (attr->psvi != avt) {  /* may have changed from realloc */
00330             attr->psvi = avt;
00331         /*
00332          * This is a "hack", but I can't see any clean method of
00333          * doing it.  If a re-alloc has taken place, then the pointer
00334          * for this AVT may have changed.  style->attVTs was set by
00335          * xsltNewAttrVT, so it needs to be re-set to the new value!
00336          */
00337         style->attVTs = avt;
00338     }
00339     }
00340     if (ret != NULL)
00341     xmlFree(ret);
00342     if (expr != NULL)
00343     xmlFree(expr);
00344 }
00345 
00346 
00358 xmlChar *
00359 xsltEvalAVT(xsltTransformContextPtr ctxt, void *avt, xmlNodePtr node) {
00360     xmlChar *ret = NULL, *tmp;
00361     xmlXPathCompExprPtr comp;
00362     xsltAttrVTPtr cur = (xsltAttrVTPtr) avt;
00363     int i;
00364     int str;
00365 
00366     if ((ctxt == NULL) || (avt == NULL) || (node == NULL))
00367         return(NULL);
00368     str = cur->strstart;
00369     for (i = 0;i < cur->nb_seg;i++) {
00370         if (str) {
00371         ret = xmlStrcat(ret, (const xmlChar *) cur->segments[i]);
00372     } else {
00373         comp = (xmlXPathCompExprPtr) cur->segments[i];
00374         tmp = xsltEvalXPathStringNs(ctxt, comp, cur->nsNr, cur->nsList);
00375         if (tmp != NULL) {
00376             if (ret != NULL) {
00377             ret = xmlStrcat(ret, tmp);
00378             xmlFree(tmp);
00379         } else {
00380             ret = tmp;
00381         }
00382         }
00383     }
00384     str = !str;
00385     }
00386     return(ret);
00387 }

Generated on Sun May 27 2012 04:19:35 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.