Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(81)

Side by Side Diff: third_party/libxslt/libxslt/templates.c

Issue 2865973002: Check in the libxslt roll script. (Closed)
Patch Set: Consistent quotes. Created 3 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « third_party/libxslt/libxslt/templates.h ('k') | third_party/libxslt/libxslt/transform.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 /*
2 * templates.c: Implementation of the template processing
3 *
4 * Reference:
5 * http://www.w3.org/TR/1999/REC-xslt-19991116
6 *
7 * See Copyright for the status of this software.
8 *
9 * daniel@veillard.com
10 */
11
12 #define IN_LIBXSLT
13 #include "libxslt.h"
14
15 #include <string.h>
16
17 #include <libxml/xmlmemory.h>
18 #include <libxml/globals.h>
19 #include <libxml/xmlerror.h>
20 #include <libxml/tree.h>
21 #include <libxml/dict.h>
22 #include <libxml/xpathInternals.h>
23 #include <libxml/parserInternals.h>
24 #include "xslt.h"
25 #include "xsltInternals.h"
26 #include "xsltutils.h"
27 #include "variables.h"
28 #include "functions.h"
29 #include "templates.h"
30 #include "transform.h"
31 #include "namespaces.h"
32 #include "attributes.h"
33
34 #ifdef WITH_XSLT_DEBUG
35 #define WITH_XSLT_DEBUG_TEMPLATES
36 #endif
37
38 /************************************************************************
39 * *
40 * Module interfaces *
41 * *
42 ************************************************************************/
43
44 /**
45 * xsltEvalXPathPredicate:
46 * @ctxt: the XSLT transformation context
47 * @comp: the XPath compiled expression
48 * @nsList: the namespaces in scope
49 * @nsNr: the number of namespaces in scope
50 *
51 * Process the expression using XPath and evaluate the result as
52 * an XPath predicate
53 *
54 * Returns 1 is the predicate was true, 0 otherwise
55 */
56 int
57 xsltEvalXPathPredicate(xsltTransformContextPtr ctxt, xmlXPathCompExprPtr comp,
58 xmlNsPtr *nsList, int nsNr) {
59 int ret;
60 xmlXPathObjectPtr res;
61 int oldNsNr;
62 xmlNsPtr *oldNamespaces;
63 xmlNodePtr oldInst;
64 int oldProximityPosition, oldContextSize;
65
66 if ((ctxt == NULL) || (ctxt->inst == NULL)) {
67 xsltTransformError(ctxt, NULL, NULL,
68 "xsltEvalXPathPredicate: No context or instruction\n");
69 return(0);
70 }
71
72 oldContextSize = ctxt->xpathCtxt->contextSize;
73 oldProximityPosition = ctxt->xpathCtxt->proximityPosition;
74 oldNsNr = ctxt->xpathCtxt->nsNr;
75 oldNamespaces = ctxt->xpathCtxt->namespaces;
76 oldInst = ctxt->inst;
77
78 ctxt->xpathCtxt->node = ctxt->node;
79 ctxt->xpathCtxt->namespaces = nsList;
80 ctxt->xpathCtxt->nsNr = nsNr;
81
82 res = xmlXPathCompiledEval(comp, ctxt->xpathCtxt);
83
84 if (res != NULL) {
85 ret = xmlXPathEvalPredicate(ctxt->xpathCtxt, res);
86 xmlXPathFreeObject(res);
87 #ifdef WITH_XSLT_DEBUG_TEMPLATES
88 XSLT_TRACE(ctxt,XSLT_TRACE_TEMPLATES,xsltGenericDebug(xsltGenericDebugCo ntext,
89 "xsltEvalXPathPredicate: returns %d\n", ret));
90 #endif
91 } else {
92 #ifdef WITH_XSLT_DEBUG_TEMPLATES
93 XSLT_TRACE(ctxt,XSLT_TRACE_TEMPLATES,xsltGenericDebug(xsltGenericDebugCo ntext,
94 "xsltEvalXPathPredicate: failed\n"));
95 #endif
96 ctxt->state = XSLT_STATE_STOPPED;
97 ret = 0;
98 }
99 ctxt->xpathCtxt->nsNr = oldNsNr;
100
101 ctxt->xpathCtxt->namespaces = oldNamespaces;
102 ctxt->inst = oldInst;
103 ctxt->xpathCtxt->contextSize = oldContextSize;
104 ctxt->xpathCtxt->proximityPosition = oldProximityPosition;
105
106 return(ret);
107 }
108
109 /**
110 * xsltEvalXPathStringNs:
111 * @ctxt: the XSLT transformation context
112 * @comp: the compiled XPath expression
113 * @nsNr: the number of namespaces in the list
114 * @nsList: the list of in-scope namespaces to use
115 *
116 * Process the expression using XPath, allowing to pass a namespace mapping
117 * context and get a string
118 *
119 * Returns the computed string value or NULL, must be deallocated by the
120 * caller.
121 */
122 xmlChar *
123 xsltEvalXPathStringNs(xsltTransformContextPtr ctxt, xmlXPathCompExprPtr comp,
124 int nsNr, xmlNsPtr *nsList) {
125 xmlChar *ret = NULL;
126 xmlXPathObjectPtr res;
127 xmlNodePtr oldInst;
128 xmlNodePtr oldNode;
129 int oldPos, oldSize;
130 int oldNsNr;
131 xmlNsPtr *oldNamespaces;
132
133 if ((ctxt == NULL) || (ctxt->inst == NULL)) {
134 xsltTransformError(ctxt, NULL, NULL,
135 "xsltEvalXPathStringNs: No context or instruction\n");
136 return(0);
137 }
138
139 oldInst = ctxt->inst;
140 oldNode = ctxt->node;
141 oldPos = ctxt->xpathCtxt->proximityPosition;
142 oldSize = ctxt->xpathCtxt->contextSize;
143 oldNsNr = ctxt->xpathCtxt->nsNr;
144 oldNamespaces = ctxt->xpathCtxt->namespaces;
145
146 ctxt->xpathCtxt->node = ctxt->node;
147 /* TODO: do we need to propagate the namespaces here ? */
148 ctxt->xpathCtxt->namespaces = nsList;
149 ctxt->xpathCtxt->nsNr = nsNr;
150 res = xmlXPathCompiledEval(comp, ctxt->xpathCtxt);
151 if (res != NULL) {
152 if (res->type != XPATH_STRING)
153 res = xmlXPathConvertString(res);
154 if (res->type == XPATH_STRING) {
155 ret = res->stringval;
156 res->stringval = NULL;
157 } else {
158 xsltTransformError(ctxt, NULL, NULL,
159 "xpath : string() function didn't return a String\n");
160 }
161 xmlXPathFreeObject(res);
162 } else {
163 ctxt->state = XSLT_STATE_STOPPED;
164 }
165 #ifdef WITH_XSLT_DEBUG_TEMPLATES
166 XSLT_TRACE(ctxt,XSLT_TRACE_TEMPLATES,xsltGenericDebug(xsltGenericDebugContex t,
167 "xsltEvalXPathString: returns %s\n", ret));
168 #endif
169 ctxt->inst = oldInst;
170 ctxt->node = oldNode;
171 ctxt->xpathCtxt->contextSize = oldSize;
172 ctxt->xpathCtxt->proximityPosition = oldPos;
173 ctxt->xpathCtxt->nsNr = oldNsNr;
174 ctxt->xpathCtxt->namespaces = oldNamespaces;
175 return(ret);
176 }
177
178 /**
179 * xsltEvalXPathString:
180 * @ctxt: the XSLT transformation context
181 * @comp: the compiled XPath expression
182 *
183 * Process the expression using XPath and get a string
184 *
185 * Returns the computed string value or NULL, must be deallocated by the
186 * caller.
187 */
188 xmlChar *
189 xsltEvalXPathString(xsltTransformContextPtr ctxt, xmlXPathCompExprPtr comp) {
190 return(xsltEvalXPathStringNs(ctxt, comp, 0, NULL));
191 }
192
193 /**
194 * xsltEvalTemplateString:
195 * @ctxt: the XSLT transformation context
196 * @contextNode: the current node in the source tree
197 * @inst: the XSLT instruction (xsl:comment, xsl:processing-instruction)
198 *
199 * Processes the sequence constructor of the given instruction on
200 * @contextNode and converts the resulting tree to a string.
201 * This is needed by e.g. xsl:comment and xsl:processing-instruction.
202 *
203 * Returns the computed string value or NULL; it's up to the caller to
204 * free the result.
205 */
206 xmlChar *
207 xsltEvalTemplateString(xsltTransformContextPtr ctxt,
208 xmlNodePtr contextNode,
209 xmlNodePtr inst)
210 {
211 xmlNodePtr oldInsert, insert = NULL;
212 xmlChar *ret;
213
214 if ((ctxt == NULL) || (contextNode == NULL) || (inst == NULL) ||
215 (inst->type != XML_ELEMENT_NODE))
216 return(NULL);
217
218 if (inst->children == NULL)
219 return(NULL);
220
221 /*
222 * This creates a temporary element-node to add the resulting
223 * text content to.
224 * OPTIMIZE TODO: Keep such an element-node in the transformation
225 * context to avoid creating it every time.
226 */
227 insert = xmlNewDocNode(ctxt->output, NULL,
228 (const xmlChar *)"fake", NULL);
229 if (insert == NULL) {
230 xsltTransformError(ctxt, NULL, contextNode,
231 "Failed to create temporary node\n");
232 return(NULL);
233 }
234 oldInsert = ctxt->insert;
235 ctxt->insert = insert;
236 /*
237 * OPTIMIZE TODO: if inst->children consists only of text-nodes.
238 */
239 xsltApplyOneTemplate(ctxt, contextNode, inst->children, NULL, NULL);
240
241 ctxt->insert = oldInsert;
242
243 ret = xmlNodeGetContent(insert);
244 if (insert != NULL)
245 xmlFreeNode(insert);
246 return(ret);
247 }
248
249 /**
250 * xsltAttrTemplateValueProcessNode:
251 * @ctxt: the XSLT transformation context
252 * @str: the attribute template node value
253 * @inst: the instruction (or LRE) in the stylesheet holding the
254 * attribute with an AVT
255 *
256 * Process the given string, allowing to pass a namespace mapping
257 * context and return the new string value.
258 *
259 * Called by:
260 * - xsltAttrTemplateValueProcess() (templates.c)
261 * - xsltEvalAttrValueTemplate() (templates.c)
262 *
263 * QUESTION: Why is this function public? It is not used outside
264 * of templates.c.
265 *
266 * Returns the computed string value or NULL, must be deallocated by the
267 * caller.
268 */
269 xmlChar *
270 xsltAttrTemplateValueProcessNode(xsltTransformContextPtr ctxt,
271 const xmlChar *str, xmlNodePtr inst)
272 {
273 xmlChar *ret = NULL;
274 const xmlChar *cur;
275 xmlChar *expr, *val;
276 xmlNsPtr *nsList = NULL;
277 int nsNr = 0;
278
279 if (str == NULL) return(NULL);
280 if (*str == 0)
281 return(xmlStrndup((xmlChar *)"", 0));
282
283 cur = str;
284 while (*cur != 0) {
285 if (*cur == '{') {
286 if (*(cur+1) == '{') { /* escaped '{' */
287 cur++;
288 ret = xmlStrncat(ret, str, cur - str);
289 cur++;
290 str = cur;
291 continue;
292 }
293 ret = xmlStrncat(ret, str, cur - str);
294 str = cur;
295 cur++;
296 while ((*cur != 0) && (*cur != '}')) {
297 /* Need to check for literal (bug539741) */
298 if ((*cur == '\'') || (*cur == '"')) {
299 char delim = *(cur++);
300 while ((*cur != 0) && (*cur != delim))
301 cur++;
302 if (*cur != 0)
303 cur++; /* skip the ending delimiter */
304 } else
305 cur++;
306 }
307 if (*cur == 0) {
308 xsltTransformError(ctxt, NULL, inst,
309 "xsltAttrTemplateValueProcessNode: unmatched '{'\n");
310 ret = xmlStrncat(ret, str, cur - str);
311 return(ret);
312 }
313 str++;
314 expr = xmlStrndup(str, cur - str);
315 if (expr == NULL)
316 return(ret);
317 else if (*expr == '{') {
318 ret = xmlStrcat(ret, expr);
319 xmlFree(expr);
320 } else {
321 xmlXPathCompExprPtr comp;
322 /*
323 * TODO: keep precompiled form around
324 */
325 if ((nsList == NULL) && (inst != NULL)) {
326 int i = 0;
327
328 nsList = xmlGetNsList(inst->doc, inst);
329 if (nsList != NULL) {
330 while (nsList[i] != NULL)
331 i++;
332 nsNr = i;
333 }
334 }
335 comp = xmlXPathCompile(expr);
336 val = xsltEvalXPathStringNs(ctxt, comp, nsNr, nsList);
337 xmlXPathFreeCompExpr(comp);
338 xmlFree(expr);
339 if (val != NULL) {
340 ret = xmlStrcat(ret, val);
341 xmlFree(val);
342 }
343 }
344 cur++;
345 str = cur;
346 } else if (*cur == '}') {
347 cur++;
348 if (*cur == '}') { /* escaped '}' */
349 ret = xmlStrncat(ret, str, cur - str);
350 cur++;
351 str = cur;
352 continue;
353 } else {
354 xsltTransformError(ctxt, NULL, inst,
355 "xsltAttrTemplateValueProcessNode: unmatched '}'\n");
356 }
357 } else
358 cur++;
359 }
360 if (cur != str) {
361 ret = xmlStrncat(ret, str, cur - str);
362 }
363
364 if (nsList != NULL)
365 xmlFree(nsList);
366
367 return(ret);
368 }
369
370 /**
371 * xsltAttrTemplateValueProcess:
372 * @ctxt: the XSLT transformation context
373 * @str: the attribute template node value
374 *
375 * Process the given node and return the new string value.
376 *
377 * Returns the computed string value or NULL, must be deallocated by the
378 * caller.
379 */
380 xmlChar *
381 xsltAttrTemplateValueProcess(xsltTransformContextPtr ctxt, const xmlChar *str) {
382 return(xsltAttrTemplateValueProcessNode(ctxt, str, NULL));
383 }
384
385 /**
386 * xsltEvalAttrValueTemplate:
387 * @ctxt: the XSLT transformation context
388 * @inst: the instruction (or LRE) in the stylesheet holding the
389 * attribute with an AVT
390 * @name: the attribute QName
391 * @ns: the attribute namespace URI
392 *
393 * Evaluate a attribute value template, i.e. the attribute value can
394 * contain expressions contained in curly braces ({}) and those are
395 * substituted by they computed value.
396 *
397 * Returns the computed string value or NULL, must be deallocated by the
398 * caller.
399 */
400 xmlChar *
401 xsltEvalAttrValueTemplate(xsltTransformContextPtr ctxt, xmlNodePtr inst,
402 const xmlChar *name, const xmlChar *ns)
403 {
404 xmlChar *ret;
405 xmlChar *expr;
406
407 if ((ctxt == NULL) || (inst == NULL) || (name == NULL) ||
408 (inst->type != XML_ELEMENT_NODE))
409 return(NULL);
410
411 expr = xsltGetNsProp(inst, name, ns);
412 if (expr == NULL)
413 return(NULL);
414
415 /*
416 * TODO: though now {} is detected ahead, it would still be good to
417 * optimize both functions to keep the splitted value if the
418 * attribute content and the XPath precompiled expressions around
419 */
420
421 ret = xsltAttrTemplateValueProcessNode(ctxt, expr, inst);
422 #ifdef WITH_XSLT_DEBUG_TEMPLATES
423 XSLT_TRACE(ctxt,XSLT_TRACE_TEMPLATES,xsltGenericDebug(xsltGenericDebugContex t,
424 "xsltEvalAttrValueTemplate: %s returns %s\n", expr, ret));
425 #endif
426 if (expr != NULL)
427 xmlFree(expr);
428 return(ret);
429 }
430
431 /**
432 * xsltEvalStaticAttrValueTemplate:
433 * @style: the XSLT stylesheet
434 * @inst: the instruction (or LRE) in the stylesheet holding the
435 * attribute with an AVT
436 * @name: the attribute Name
437 * @ns: the attribute namespace URI
438 * @found: indicator whether the attribute is present
439 *
440 * Check if an attribute value template has a static value, i.e. the
441 * attribute value does not contain expressions contained in curly braces ({})
442 *
443 * Returns the static string value or NULL, must be deallocated by the
444 * caller.
445 */
446 const xmlChar *
447 xsltEvalStaticAttrValueTemplate(xsltStylesheetPtr style, xmlNodePtr inst,
448 const xmlChar *name, const xmlChar *ns, int *found) {
449 const xmlChar *ret;
450 xmlChar *expr;
451
452 if ((style == NULL) || (inst == NULL) || (name == NULL) ||
453 (inst->type != XML_ELEMENT_NODE))
454 return(NULL);
455
456 expr = xsltGetNsProp(inst, name, ns);
457 if (expr == NULL) {
458 *found = 0;
459 return(NULL);
460 }
461 *found = 1;
462
463 ret = xmlStrchr(expr, '{');
464 if (ret != NULL) {
465 xmlFree(expr);
466 return(NULL);
467 }
468 ret = xmlDictLookup(style->dict, expr, -1);
469 xmlFree(expr);
470 return(ret);
471 }
472
473 /**
474 * xsltAttrTemplateProcess:
475 * @ctxt: the XSLT transformation context
476 * @target: the element where the attribute will be grafted
477 * @attr: the attribute node of a literal result element
478 *
479 * Process one attribute of a Literal Result Element (in the stylesheet).
480 * Evaluates Attribute Value Templates and copies the attribute over to
481 * the result element.
482 * This does *not* process attribute sets (xsl:use-attribute-set).
483 *
484 *
485 * Returns the generated attribute node.
486 */
487 xmlAttrPtr
488 xsltAttrTemplateProcess(xsltTransformContextPtr ctxt, xmlNodePtr target,
489 xmlAttrPtr attr)
490 {
491 const xmlChar *value;
492 xmlAttrPtr ret;
493
494 if ((ctxt == NULL) || (attr == NULL) || (target == NULL) ||
495 (target->type != XML_ELEMENT_NODE))
496 return(NULL);
497
498 if (attr->type != XML_ATTRIBUTE_NODE)
499 return(NULL);
500
501 /*
502 * Skip all XSLT attributes.
503 */
504 #ifdef XSLT_REFACTORED
505 if (attr->psvi == xsltXSLTAttrMarker)
506 return(NULL);
507 #else
508 if ((attr->ns != NULL) && xmlStrEqual(attr->ns->href, XSLT_NAMESPACE))
509 return(NULL);
510 #endif
511 /*
512 * Get the value.
513 */
514 if (attr->children != NULL) {
515 if ((attr->children->type != XML_TEXT_NODE) ||
516 (attr->children->next != NULL))
517 {
518 xsltTransformError(ctxt, NULL, attr->parent,
519 "Internal error: The children of an attribute node of a "
520 "literal result element are not in the expected form.\n");
521 return(NULL);
522 }
523 value = attr->children->content;
524 if (value == NULL)
525 value = xmlDictLookup(ctxt->dict, BAD_CAST "", 0);
526 } else
527 value = xmlDictLookup(ctxt->dict, BAD_CAST "", 0);
528 /*
529 * Overwrite duplicates.
530 */
531 ret = target->properties;
532 while (ret != NULL) {
533 if (((attr->ns != NULL) == (ret->ns != NULL)) &&
534 xmlStrEqual(ret->name, attr->name) &&
535 ((attr->ns == NULL) || xmlStrEqual(ret->ns->href, attr->ns->href)))
536 {
537 break;
538 }
539 ret = ret->next;
540 }
541 if (ret != NULL) {
542 /* free the existing value */
543 xmlFreeNodeList(ret->children);
544 ret->children = ret->last = NULL;
545 /*
546 * Adjust ns-prefix if needed.
547 */
548 if ((ret->ns != NULL) &&
549 (! xmlStrEqual(ret->ns->prefix, attr->ns->prefix)))
550 {
551 ret->ns = xsltGetNamespace(ctxt, attr->parent, attr->ns, target);
552 }
553 } else {
554 /* create a new attribute */
555 if (attr->ns != NULL)
556 ret = xmlNewNsProp(target,
557 xsltGetNamespace(ctxt, attr->parent, attr->ns, target),
558 attr->name, NULL);
559 else
560 ret = xmlNewNsProp(target, NULL, attr->name, NULL);
561 }
562 /*
563 * Set the value.
564 */
565 if (ret != NULL) {
566 xmlNodePtr text;
567
568 text = xmlNewText(NULL);
569 if (text != NULL) {
570 ret->last = ret->children = text;
571 text->parent = (xmlNodePtr) ret;
572 text->doc = ret->doc;
573
574 if (attr->psvi != NULL) {
575 /*
576 * Evaluate the Attribute Value Template.
577 */
578 xmlChar *val;
579 val = xsltEvalAVT(ctxt, attr->psvi, attr->parent);
580 if (val == NULL) {
581 /*
582 * TODO: Damn, we need an easy mechanism to report
583 * qualified names!
584 */
585 if (attr->ns) {
586 xsltTransformError(ctxt, NULL, attr->parent,
587 "Internal error: Failed to evaluate the AVT "
588 "of attribute '{%s}%s'.\n",
589 attr->ns->href, attr->name);
590 } else {
591 xsltTransformError(ctxt, NULL, attr->parent,
592 "Internal error: Failed to evaluate the AVT "
593 "of attribute '%s'.\n",
594 attr->name);
595 }
596 text->content = xmlStrdup(BAD_CAST "");
597 } else {
598 text->content = val;
599 }
600 } else if ((ctxt->internalized) && (target != NULL) &&
601 (target->doc != NULL) &&
602 (target->doc->dict == ctxt->dict) &&
603 xmlDictOwns(ctxt->dict, value)) {
604 text->content = (xmlChar *) value;
605 } else {
606 text->content = xmlStrdup(value);
607 }
608 }
609 } else {
610 if (attr->ns) {
611 xsltTransformError(ctxt, NULL, attr->parent,
612 "Internal error: Failed to create attribute '{%s}%s'.\n",
613 attr->ns->href, attr->name);
614 } else {
615 xsltTransformError(ctxt, NULL, attr->parent,
616 "Internal error: Failed to create attribute '%s'.\n",
617 attr->name);
618 }
619 }
620 return(ret);
621 }
622
623
624 /**
625 * xsltAttrListTemplateProcess:
626 * @ctxt: the XSLT transformation context
627 * @target: the element where the attributes will be grafted
628 * @attrs: the first attribute
629 *
630 * Processes all attributes of a Literal Result Element.
631 * Attribute references are applied via xsl:use-attribute-set
632 * attributes.
633 * Copies all non XSLT-attributes over to the @target element
634 * and evaluates Attribute Value Templates.
635 *
636 * Called by xsltApplySequenceConstructor() (transform.c).
637 *
638 * Returns a new list of attribute nodes, or NULL in case of error.
639 * (Don't assign the result to @target->properties; if
640 * the result is NULL, you'll get memory leaks, since the
641 * attributes will be disattached.)
642 */
643 xmlAttrPtr
644 xsltAttrListTemplateProcess(xsltTransformContextPtr ctxt,
645 xmlNodePtr target, xmlAttrPtr attrs)
646 {
647 xmlAttrPtr attr, copy, last;
648 xmlNodePtr oldInsert, text;
649 xmlNsPtr origNs = NULL, copyNs = NULL;
650 const xmlChar *value;
651 xmlChar *valueAVT;
652
653 if ((ctxt == NULL) || (target == NULL) || (attrs == NULL) ||
654 (target->type != XML_ELEMENT_NODE))
655 return(NULL);
656
657 oldInsert = ctxt->insert;
658 ctxt->insert = target;
659
660 /*
661 * Instantiate LRE-attributes.
662 */
663 if (target->properties) {
664 last = target->properties;
665 while (last->next != NULL)
666 last = last->next;
667 } else {
668 last = NULL;
669 }
670 attr = attrs;
671 do {
672 /*
673 * Skip XSLT attributes.
674 */
675 #ifdef XSLT_REFACTORED
676 if (attr->psvi == xsltXSLTAttrMarker) {
677 goto next_attribute;
678 }
679 #else
680 if ((attr->ns != NULL) &&
681 xmlStrEqual(attr->ns->href, XSLT_NAMESPACE))
682 {
683 goto next_attribute;
684 }
685 #endif
686 /*
687 * Get the value.
688 */
689 if (attr->children != NULL) {
690 if ((attr->children->type != XML_TEXT_NODE) ||
691 (attr->children->next != NULL))
692 {
693 xsltTransformError(ctxt, NULL, attr->parent,
694 "Internal error: The children of an attribute node of a "
695 "literal result element are not in the expected form.\n");
696 goto error;
697 }
698 value = attr->children->content;
699 if (value == NULL)
700 value = xmlDictLookup(ctxt->dict, BAD_CAST "", 0);
701 } else
702 value = xmlDictLookup(ctxt->dict, BAD_CAST "", 0);
703
704 /*
705 * Create a new attribute.
706 */
707 copy = xmlNewDocProp(target->doc, attr->name, NULL);
708 if (copy == NULL) {
709 if (attr->ns) {
710 xsltTransformError(ctxt, NULL, attr->parent,
711 "Internal error: Failed to create attribute '{%s}%s'.\n",
712 attr->ns->href, attr->name);
713 } else {
714 xsltTransformError(ctxt, NULL, attr->parent,
715 "Internal error: Failed to create attribute '%s'.\n",
716 attr->name);
717 }
718 goto error;
719 }
720 /*
721 * Attach it to the target element.
722 */
723 copy->parent = target;
724 if (last == NULL) {
725 target->properties = copy;
726 last = copy;
727 } else {
728 last->next = copy;
729 copy->prev = last;
730 last = copy;
731 }
732 /*
733 * Set the namespace. Avoid lookups of same namespaces.
734 */
735 if (attr->ns != origNs) {
736 origNs = attr->ns;
737 if (attr->ns != NULL) {
738 #ifdef XSLT_REFACTORED
739 copyNs = xsltGetSpecialNamespace(ctxt, attr->parent,
740 attr->ns->href, attr->ns->prefix, target);
741 #else
742 copyNs = xsltGetNamespace(ctxt, attr->parent,
743 attr->ns, target);
744 #endif
745 if (copyNs == NULL)
746 goto error;
747 } else
748 copyNs = NULL;
749 }
750 copy->ns = copyNs;
751
752 /*
753 * Set the value.
754 */
755 text = xmlNewText(NULL);
756 if (text != NULL) {
757 copy->last = copy->children = text;
758 text->parent = (xmlNodePtr) copy;
759 text->doc = copy->doc;
760
761 if (attr->psvi != NULL) {
762 /*
763 * Evaluate the Attribute Value Template.
764 */
765 valueAVT = xsltEvalAVT(ctxt, attr->psvi, attr->parent);
766 if (valueAVT == NULL) {
767 /*
768 * TODO: Damn, we need an easy mechanism to report
769 * qualified names!
770 */
771 if (attr->ns) {
772 xsltTransformError(ctxt, NULL, attr->parent,
773 "Internal error: Failed to evaluate the AVT "
774 "of attribute '{%s}%s'.\n",
775 attr->ns->href, attr->name);
776 } else {
777 xsltTransformError(ctxt, NULL, attr->parent,
778 "Internal error: Failed to evaluate the AVT "
779 "of attribute '%s'.\n",
780 attr->name);
781 }
782 text->content = xmlStrdup(BAD_CAST "");
783 goto error;
784 } else {
785 text->content = valueAVT;
786 }
787 } else if ((ctxt->internalized) &&
788 (target->doc != NULL) &&
789 (target->doc->dict == ctxt->dict) &&
790 xmlDictOwns(ctxt->dict, value))
791 {
792 text->content = (xmlChar *) value;
793 } else {
794 text->content = xmlStrdup(value);
795 }
796 if ((copy != NULL) && (text != NULL) &&
797 (xmlIsID(copy->doc, copy->parent, copy)))
798 xmlAddID(NULL, copy->doc, text->content, copy);
799 }
800
801 next_attribute:
802 attr = attr->next;
803 } while (attr != NULL);
804
805 /*
806 * Apply attribute-sets.
807 * The creation of such attributes will not overwrite any existing
808 * attribute.
809 */
810 attr = attrs;
811 do {
812 #ifdef XSLT_REFACTORED
813 if ((attr->psvi == xsltXSLTAttrMarker) &&
814 xmlStrEqual(attr->name, (const xmlChar *)"use-attribute-sets"))
815 {
816 xsltApplyAttributeSet(ctxt, ctxt->node, (xmlNodePtr) attr, NULL);
817 }
818 #else
819 if ((attr->ns != NULL) &&
820 xmlStrEqual(attr->name, (const xmlChar *)"use-attribute-sets") &&
821 xmlStrEqual(attr->ns->href, XSLT_NAMESPACE))
822 {
823 xsltApplyAttributeSet(ctxt, ctxt->node, (xmlNodePtr) attr, NULL);
824 }
825 #endif
826 attr = attr->next;
827 } while (attr != NULL);
828
829 ctxt->insert = oldInsert;
830 return(target->properties);
831
832 error:
833 ctxt->insert = oldInsert;
834 return(NULL);
835 }
836
837
838 /**
839 * xsltTemplateProcess:
840 * @ctxt: the XSLT transformation context
841 * @node: the attribute template node
842 *
843 * Obsolete. Don't use it.
844 *
845 * Returns NULL.
846 */
847 xmlNodePtr *
848 xsltTemplateProcess(xsltTransformContextPtr ctxt ATTRIBUTE_UNUSED, xmlNodePtr no de) {
849 if (node == NULL)
850 return(NULL);
851
852 return(0);
853 }
854
855
OLDNEW
« no previous file with comments | « third_party/libxslt/libxslt/templates.h ('k') | third_party/libxslt/libxslt/transform.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698