VirtualBox

source: vbox/trunk/src/libs/libxslt-1.1.22/libxslt/attrvt.c@ 8857

最後變更 在這個檔案從8857是 7296,由 vboxsync 提交於 17 年 前

Added libxslt-1.1.22 sources.

  • 屬性 svn:eol-style 設為 native
  • 屬性 svn:keywords 設為 Date Revision Author Id
檔案大小: 9.4 KB
 
1/*
2 * attrvt.c: Implementation of the XSL Transformation 1.0 engine
3 * attribute value template handling part.
4 *
5 * References:
6 * http://www.w3.org/TR/1999/REC-xslt-19991116
7 *
8 * Michael Kay "XSLT Programmer's Reference" pp 637-643
9 * Writing Multiple Output Files
10 *
11 * See Copyright for the status of this software.
12 *
13 * [email protected]
14 */
15
16#define IN_LIBXSLT
17#include "libxslt.h"
18
19#include <string.h>
20
21#include <libxml/xmlmemory.h>
22#include <libxml/tree.h>
23#include <libxml/xpath.h>
24#include <libxml/xpathInternals.h>
25#include "xslt.h"
26#include "xsltutils.h"
27#include "xsltInternals.h"
28#include "templates.h"
29
30#ifdef WITH_XSLT_DEBUG
31#define WITH_XSLT_DEBUG_AVT
32#endif
33
34#define MAX_AVT_SEG 10
35
36typedef struct _xsltAttrVT xsltAttrVT;
37typedef xsltAttrVT *xsltAttrVTPtr;
38struct _xsltAttrVT {
39 struct _xsltAttrVT *next; /* next xsltAttrVT */
40 int nb_seg; /* Number of segments */
41 int max_seg; /* max capacity before re-alloc needed */
42 int strstart; /* is the start a string */
43 /*
44 * the namespaces in scope
45 */
46 xmlNsPtr *nsList;
47 int nsNr;
48 /*
49 * the content is an alternate of string and xmlXPathCompExprPtr
50 */
51 void *segments[MAX_AVT_SEG];
52};
53
54/**
55 * xsltNewAttrVT:
56 * @style: a XSLT process context
57 *
58 * Build a new xsltAttrVT structure
59 *
60 * Returns the structure or NULL in case of error
61 */
62static xsltAttrVTPtr
63xsltNewAttrVT(xsltStylesheetPtr style) {
64 xsltAttrVTPtr cur;
65
66 cur = (xsltAttrVTPtr) xmlMalloc(sizeof(xsltAttrVT));
67 if (cur == NULL) {
68 xsltTransformError(NULL, style, NULL,
69 "xsltNewAttrVTPtr : malloc failed\n");
70 if (style != NULL) style->errors++;
71 return(NULL);
72 }
73 memset(cur, 0, sizeof(xsltAttrVT));
74
75 cur->nb_seg = 0;
76 cur->max_seg = MAX_AVT_SEG;
77 cur->strstart = 0;
78 cur->next = style->attVTs;
79 /*
80 * Note: this pointer may be changed by a re-alloc within xsltCompileAttr,
81 * so that code may change the stylesheet pointer also!
82 */
83 style->attVTs = (xsltAttrVTPtr) cur;
84
85 return(cur);
86}
87
88/**
89 * xsltFreeAttrVT:
90 * @avt: pointer to an xsltAttrVT structure
91 *
92 * Free up the memory associated to the attribute value template
93 */
94static void
95xsltFreeAttrVT(xsltAttrVTPtr avt) {
96 int i;
97
98 if (avt == NULL) return;
99
100 if (avt->strstart == 1) {
101 for (i = 0;i < avt->nb_seg; i += 2)
102 if (avt->segments[i] != NULL)
103 xmlFree((xmlChar *) avt->segments[i]);
104 for (i = 1;i < avt->nb_seg; i += 2)
105 xmlXPathFreeCompExpr((xmlXPathCompExprPtr) avt->segments[i]);
106 } else {
107 for (i = 0;i < avt->nb_seg; i += 2)
108 xmlXPathFreeCompExpr((xmlXPathCompExprPtr) avt->segments[i]);
109 for (i = 1;i < avt->nb_seg; i += 2)
110 if (avt->segments[i] != NULL)
111 xmlFree((xmlChar *) avt->segments[i]);
112 }
113 if (avt->nsList != NULL)
114 xmlFree(avt->nsList);
115 xmlFree(avt);
116}
117
118/**
119 * xsltFreeAVTList:
120 * @avt: pointer to an list of AVT structures
121 *
122 * Free up the memory associated to the attribute value templates
123 */
124void
125xsltFreeAVTList(void *avt) {
126 xsltAttrVTPtr cur = (xsltAttrVTPtr) avt, next;
127
128 while (cur != NULL) {
129 next = cur->next;
130 xsltFreeAttrVT(cur);
131 cur = next;
132 }
133}
134/**
135 * xsltSetAttrVTsegment:
136 * @ avt: pointer to an xsltAttrVT structure
137 * @ val: the value to be set to the next available segment
138 *
139 * Within xsltCompileAttr there are several places where a value
140 * needs to be added to the 'segments' array within the xsltAttrVT
141 * structure, and at each place the allocated size may have to be
142 * re-allocated. This routine takes care of that situation.
143 *
144 * Returns the avt pointer, which may have been changed by a re-alloc
145 */
146static xsltAttrVTPtr
147xsltSetAttrVTsegment(xsltAttrVTPtr avt, void *val) {
148 if (avt->nb_seg >= avt->max_seg) {
149 avt = (xsltAttrVTPtr) xmlRealloc(avt, sizeof(xsltAttrVT) +
150 avt->max_seg * sizeof(void *));
151 if (avt == NULL) {
152 return NULL;
153 }
154 memset(&avt->segments[avt->nb_seg], 0, MAX_AVT_SEG*sizeof(void *));
155 avt->max_seg += MAX_AVT_SEG;
156 }
157 avt->segments[avt->nb_seg++] = val;
158 return avt;
159}
160
161/**
162 * xsltCompileAttr:
163 * @style: a XSLT process context
164 * @attr: the attribute coming from the stylesheet.
165 *
166 * Precompile an attribute in a stylesheet, basically it checks if it is
167 * an attrubute value template, and if yes establish some structures needed
168 * to process it at transformation time.
169 */
170void
171xsltCompileAttr(xsltStylesheetPtr style, xmlAttrPtr attr) {
172 const xmlChar *str;
173 const xmlChar *cur;
174 xmlChar *ret = NULL;
175 xmlChar *expr = NULL;
176 xsltAttrVTPtr avt;
177 int i = 0, lastavt = 0;
178
179 if ((style == NULL) || (attr == NULL) || (attr->children == NULL))
180 return;
181 if ((attr->children->type != XML_TEXT_NODE) ||
182 (attr->children->next != NULL)) {
183 xsltTransformError(NULL, style, attr->parent,
184 "Attribute '%s': The content is expected to be a single text "
185 "node when compiling an AVT.\n", attr->name);
186 style->errors++;
187 return;
188 }
189 str = attr->children->content;
190 if ((xmlStrchr(str, '{') == NULL) &&
191 (xmlStrchr(str, '}') == NULL)) return;
192
193#ifdef WITH_XSLT_DEBUG_AVT
194 xsltGenericDebug(xsltGenericDebugContext,
195 "Found AVT %s: %s\n", attr->name, str);
196#endif
197 if (attr->psvi != NULL) {
198#ifdef WITH_XSLT_DEBUG_AVT
199 xsltGenericDebug(xsltGenericDebugContext,
200 "AVT %s: already compiled\n", attr->name);
201#endif
202 return;
203 }
204 /*
205 * Create a new AVT object.
206 */
207 avt = xsltNewAttrVT(style);
208 if (avt == NULL)
209 return;
210 attr->psvi = avt;
211
212 avt->nsList = xmlGetNsList(attr->doc, attr->parent);
213 if (avt->nsList != NULL) {
214 while (avt->nsList[i] != NULL)
215 i++;
216 }
217 avt->nsNr = i;
218
219 cur = str;
220 while (*cur != 0) {
221 if (*cur == '{') {
222 if (*(cur+1) == '{') { /* escaped '{' */
223 cur++;
224 ret = xmlStrncat(ret, str, cur - str);
225 cur++;
226 str = cur;
227 continue;
228 }
229 if (*(cur+1) == '}') { /* skip empty AVT */
230 ret = xmlStrncat(ret, str, cur - str);
231 cur += 2;
232 str = cur;
233 continue;
234 }
235 if ((ret != NULL) || (cur - str > 0)) {
236 ret = xmlStrncat(ret, str, cur - str);
237 str = cur;
238 if (avt->nb_seg == 0)
239 avt->strstart = 1;
240 if ((avt = xsltSetAttrVTsegment(avt, (void *) ret)) == NULL)
241 goto error;
242 ret = NULL;
243 lastavt = 0;
244 }
245
246 cur++;
247 while ((*cur != 0) && (*cur != '}')) cur++;
248 if (*cur == 0) {
249 xsltTransformError(NULL, style, attr->parent,
250 "Attribute '%s': The AVT has an unmatched '{'.\n",
251 attr->name);
252 style->errors++;
253 goto error;
254 }
255 str++;
256 expr = xmlStrndup(str, cur - str);
257 if (expr == NULL) {
258 /*
259 * TODO: What needs to be done here?
260 */
261 XSLT_TODO
262 goto error;
263 } else {
264 xmlXPathCompExprPtr comp;
265
266 comp = xsltXPathCompile(style, expr);
267 if (comp == NULL) {
268 xsltTransformError(NULL, style, attr->parent,
269 "Attribute '%s': Failed to compile the expression "
270 "'%s' in the AVT.\n", attr->name, expr);
271 style->errors++;
272 goto error;
273 }
274 if (avt->nb_seg == 0)
275 avt->strstart = 0;
276 if (lastavt == 1) {
277 if ((avt = xsltSetAttrVTsegment(avt, NULL)) == NULL)
278 goto error;
279 }
280 if ((avt = xsltSetAttrVTsegment(avt, (void *) comp)) == NULL)
281 goto error;
282 lastavt = 1;
283 xmlFree(expr);
284 expr = NULL;
285 }
286 cur++;
287 str = cur;
288 } else if (*cur == '}') {
289 cur++;
290 if (*cur == '}') { /* escaped '}' */
291 ret = xmlStrncat(ret, str, cur - str);
292 cur++;
293 str = cur;
294 continue;
295 } else {
296 xsltTransformError(NULL, style, attr->parent,
297 "Attribute '%s': The AVT has an unmatched '}'.\n",
298 attr->name);
299 goto error;
300 }
301 } else
302 cur++;
303 }
304 if ((ret != NULL) || (cur - str > 0)) {
305 ret = xmlStrncat(ret, str, cur - str);
306 str = cur;
307 if (avt->nb_seg == 0)
308 avt->strstart = 1;
309 if ((avt = xsltSetAttrVTsegment(avt, (void *) ret)) == NULL)
310 goto error;
311 ret = NULL;
312 }
313
314error:
315 if (avt == NULL) {
316 xsltTransformError(NULL, style, attr->parent,
317 "xsltCompileAttr: malloc problem\n");
318 } else {
319 if (attr->psvi != avt) { /* may have changed from realloc */
320 attr->psvi = avt;
321 /*
322 * This is a "hack", but I can't see any clean method of
323 * doing it. If a re-alloc has taken place, then the pointer
324 * for this AVT may have changed. style->attVTs was set by
325 * xsltNewAttrVT, so it needs to be re-set to the new value!
326 */
327 style->attVTs = avt;
328 }
329 }
330 if (ret != NULL)
331 xmlFree(ret);
332 if (expr != NULL)
333 xmlFree(expr);
334}
335
336
337/**
338 * xsltEvalAVT:
339 * @ctxt: the XSLT transformation context
340 * @avt: the prevompiled attribute value template info
341 * @node: the node hosting the attribute
342 *
343 * Process the given AVT, and return the new string value.
344 *
345 * Returns the computed string value or NULL, must be deallocated by the
346 * caller.
347 */
348xmlChar *
349xsltEvalAVT(xsltTransformContextPtr ctxt, void *avt, xmlNodePtr node) {
350 xmlChar *ret = NULL, *tmp;
351 xmlXPathCompExprPtr comp;
352 xsltAttrVTPtr cur = (xsltAttrVTPtr) avt;
353 int i;
354 int str;
355
356 if ((ctxt == NULL) || (avt == NULL) || (node == NULL))
357 return(NULL);
358 str = cur->strstart;
359 for (i = 0;i < cur->nb_seg;i++) {
360 if (str) {
361 ret = xmlStrcat(ret, (const xmlChar *) cur->segments[i]);
362 } else {
363 comp = (xmlXPathCompExprPtr) cur->segments[i];
364 tmp = xsltEvalXPathStringNs(ctxt, comp, cur->nsNr, cur->nsList);
365 if (tmp != NULL) {
366 if (ret != NULL) {
367 ret = xmlStrcat(ret, tmp);
368 xmlFree(tmp);
369 } else {
370 ret = tmp;
371 }
372 }
373 }
374 str = !str;
375 }
376 return(ret);
377}
注意: 瀏覽 TracBrowser 來幫助您使用儲存庫瀏覽器

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette