VirtualBox

source: vbox/trunk/src/libs/libxslt-1.1.22/libxslt/templates.c@ 24345

Last change on this file since 24345 was 7296, checked in by vboxsync, 17 years ago

Added libxslt-1.1.22 sources.

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

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