ReactOS 0.4.16-dev-2207-geb15453
attributes.c
Go to the documentation of this file.
1/*
2 * attributes.c: Implementation of the XSLT attributes handling
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/tree.h>
19#include <libxml/hash.h>
20#include <libxml/xmlerror.h>
21#include <libxml/uri.h>
23#include "xslt.h"
24#include "xsltInternals.h"
25#include "xsltutils.h"
26#include "attributes.h"
27#include "namespaces.h"
28#include "templates.h"
29#include "imports.h"
30#include "transform.h"
31#include "preproc.h"
32
33#define WITH_XSLT_DEBUG_ATTRIBUTES
34#ifdef WITH_XSLT_DEBUG
35#define WITH_XSLT_DEBUG_ATTRIBUTES
36#endif
37
38/*
39 * Useful macros
40 */
41#ifdef IS_BLANK
42#undef IS_BLANK
43#endif
44
45#define IS_BLANK(c) (((c) == 0x20) || ((c) == 0x09) || ((c) == 0xA) || \
46 ((c) == 0x0D))
47
48#define IS_BLANK_NODE(n) \
49 (((n)->type == XML_TEXT_NODE) && (xsltIsBlank((n)->content)))
50
51#define ATTRSET_UNRESOLVED 0
52#define ATTRSET_RESOLVING 1
53#define ATTRSET_RESOLVED 2
54
55
56/*
57 * The in-memory structure corresponding to an XSLT Attribute in
58 * an attribute set
59 */
60
61
65 struct _xsltAttrElem *next;/* chained list */
66 xmlNodePtr attr; /* the xsl:attribute definition */
67};
68
72 struct _xsltUseAttrSet *next; /* chained list */
74 const xmlChar *ns;
75};
76
80 int state;
81 xsltAttrElemPtr attrs; /* list head */
83};
84
90 int error;
91};
92
93static void
96 const xmlChar *ns, int depth);
97
98/************************************************************************
99 * *
100 * XSLT Attribute handling *
101 * *
102 ************************************************************************/
103
112static xsltAttrElemPtr
115
117 if (cur == NULL) {
119 "xsltNewAttrElem : malloc failed\n");
120 return(NULL);
121 }
122 memset(cur, 0, sizeof(xsltAttrElem));
123 cur->attr = attr;
124 return(cur);
125}
126
133static void
135 xmlFree(attr);
136}
137
144static void
147
148 while (list != NULL) {
149 next = list->next;
151 list = next;
152 }
153}
154
164static xsltAttrElemPtr
167
168 if (attr == NULL)
169 return(list);
170 if (list == NULL)
171 return(xsltNewAttrElem(attr));
172 cur = list;
173 while (cur != NULL) {
174 next = cur->next;
175 if (next == NULL) {
176 cur->next = xsltNewAttrElem(attr);
177 return(list);
178 }
179 cur = next;
180 }
181 return(list);
182}
183
194xsltNewUseAttrSet(const xmlChar *ncname, const xmlChar *ns) {
196
198 if (cur == NULL) {
200 "xsltNewUseAttrSet : malloc failed\n");
201 return(NULL);
202 }
203 memset(cur, 0, sizeof(xsltUseAttrSet));
204 cur->ncname = ncname;
205 cur->ns = ns;
206 return(cur);
207}
208
215static void
217 xmlFree(use);
218}
219
226static void
229
230 while (list != NULL) {
231 next = list->next;
233 list = next;
234 }
235}
236
249 const xmlChar *ns) {
251
252 if (ncname == NULL)
253 return(list);
254 if (list == NULL)
255 return(xsltNewUseAttrSet(ncname, ns));
256 cur = list;
257 while (cur != NULL) {
258 if ((cur->ncname == ncname) && (cur->ns == ns))
259 return(list);
260 next = cur->next;
261 if (next == NULL) {
262 cur->next = xsltNewUseAttrSet(ncname, ns);
263 return(list);
264 }
265 cur = next;
266 }
267 return(list);
268}
269
277static xsltAttrSetPtr
280
282 if (cur == NULL) {
284 "xsltNewAttrSet : malloc failed\n");
285 return(NULL);
286 }
287 memset(cur, 0, sizeof(xsltAttrSet));
288 return(cur);
289}
290
297static void
299 if (set == NULL)
300 return;
301
303 xsltFreeUseAttrSetList(set->useAttrSets);
304 xmlFree(set);
305}
306
315static void
318 xsltAttrElemPtr old = other->attrs;
319 int add;
320
321 while (old != NULL) {
322 /*
323 * Check that the attribute is not yet in the list
324 */
325 cur = set->attrs;
326 add = 1;
327 while (cur != NULL) {
328 xsltStylePreCompPtr curComp = cur->attr->psvi;
329 xsltStylePreCompPtr oldComp = old->attr->psvi;
330
331 if ((curComp->name == oldComp->name) &&
332 (curComp->ns == oldComp->ns)) {
333 add = 0;
334 break;
335 }
336 if (cur->next == NULL)
337 break;
338 cur = cur->next;
339 }
340
341 if (add == 1) {
342 if (cur == NULL) {
343 set->attrs = xsltNewAttrElem(old->attr);
344 } else if (add) {
345 cur->next = xsltNewAttrElem(old->attr);
346 }
347 }
348
349 old = old->next;
350 }
351}
352
353/************************************************************************
354 * *
355 * Module interfaces *
356 * *
357 ************************************************************************/
358
367void
369 const xmlChar *ncname;
370 const xmlChar *prefix;
371 const xmlChar *nsUri = NULL;
372 xmlChar *value;
373 xmlNodePtr child;
375
376 if ((cur == NULL) || (style == NULL) || (cur->type != XML_ELEMENT_NODE))
377 return;
378
379 value = xmlGetNsProp(cur, (const xmlChar *)"name", NULL);
380 if ((value == NULL) || (*value == 0)) {
382 "xsl:attribute-set : name is missing\n");
383 if (value)
384 xmlFree(value);
385 return;
386 }
387
388 if (xmlValidateQName(value, 0)) {
390 "xsl:attribute-set : The name '%s' is not a valid QName.\n",
391 value);
392 style->errors++;
393 xmlFree(value);
394 return;
395 }
396
397 ncname = xsltSplitQName(style->dict, value, &prefix);
398 xmlFree(value);
399 value = NULL;
400 if (prefix != NULL) {
401 xmlNsPtr ns = xmlSearchNs(style->doc, cur, prefix);
402 if (ns == NULL) {
404 "xsl:attribute-set : No namespace found for QName '%s:%s'\n",
405 prefix, ncname);
406 style->errors++;
407 return;
408 }
409 nsUri = ns->href;
410 }
411
412 if (style->attributeSets == NULL) {
413#ifdef WITH_XSLT_DEBUG_ATTRIBUTES
415 "creating attribute set table\n");
416#endif
417 style->attributeSets = xmlHashCreate(10);
418 }
419 if (style->attributeSets == NULL)
420 return;
421
422 set = xmlHashLookup2(style->attributeSets, ncname, nsUri);
423 if (set == NULL) {
425 if ((set == NULL) ||
426 (xmlHashAddEntry2(style->attributeSets, ncname, nsUri, set) < 0)) {
427 xsltGenericError(xsltGenericErrorContext, "memory error\n");
429 return;
430 }
431 }
432
433 /*
434 * Parse the content. Only xsl:attribute elements are allowed.
435 */
436 child = cur->children;
437 while (child != NULL) {
438 /*
439 * Report invalid nodes.
440 */
441 if ((child->type != XML_ELEMENT_NODE) ||
442 (child->ns == NULL) ||
443 (! IS_XSLT_ELEM(child)))
444 {
445 if (child->type == XML_ELEMENT_NODE)
447 "xsl:attribute-set : unexpected child %s\n",
448 child->name);
449 else
451 "xsl:attribute-set : child of unexpected type\n");
452 } else if (!IS_XSLT_NAME(child, "attribute")) {
454 "xsl:attribute-set : unexpected child xsl:%s\n",
455 child->name);
456 } else {
457#ifdef WITH_XSLT_DEBUG_ATTRIBUTES
459 "add attribute to list %s\n", ncname);
460#endif
462 if (child->children != NULL) {
463#ifdef XSLT_REFACTORED
464 xsltParseSequenceConstructor(XSLT_CCTXT(style),
465 child->children);
466#else
468#endif
469 }
470 if (child->psvi == NULL) {
472 "xsl:attribute-set : internal error, attribute %s not "
473 "compiled\n", child->name);
474 }
475 else {
476 set->attrs = xsltAddAttrElemList(set->attrs, child);
477 }
478 }
479
480 child = child->next;
481 }
482
483 /*
484 * Process attribute "use-attribute-sets".
485 */
486 value = xmlGetNsProp(cur, BAD_CAST "use-attribute-sets", NULL);
487 if (value != NULL) {
488 const xmlChar *curval, *endval;
489 curval = value;
490 while (*curval != 0) {
491 while (IS_BLANK(*curval)) curval++;
492 if (*curval == 0)
493 break;
494 endval = curval;
495 while ((*endval != 0) && (!IS_BLANK(*endval))) endval++;
496 curval = xmlDictLookup(style->dict, curval, endval - curval);
497 if (curval) {
498 const xmlChar *ncname2 = NULL;
499 const xmlChar *prefix2 = NULL;
500 const xmlChar *nsUri2 = NULL;
501
502#ifdef WITH_XSLT_DEBUG_ATTRIBUTES
504 "xsl:attribute-set : %s adds use %s\n", ncname, curval);
505#endif
506
507 if (xmlValidateQName(curval, 0)) {
509 "xsl:attribute-set : The name '%s' in "
510 "use-attribute-sets is not a valid QName.\n", curval);
511 style->errors++;
512 xmlFree(value);
513 return;
514 }
515
516 ncname2 = xsltSplitQName(style->dict, curval, &prefix2);
517 if (prefix2 != NULL) {
518 xmlNsPtr ns2 = xmlSearchNs(style->doc, cur, prefix2);
519 if (ns2 == NULL) {
521 "xsl:attribute-set : No namespace found for QName "
522 "'%s:%s' in use-attribute-sets\n",
523 prefix2, ncname2);
524 style->errors++;
525 xmlFree(value);
526 return;
527 }
528 nsUri2 = ns2->href;
529 }
530 set->useAttrSets = xsltAddUseAttrSetList(set->useAttrSets,
531 ncname2, nsUri2);
532 }
533 curval = endval;
534 }
535 xmlFree(value);
536 value = NULL;
537 }
538
539#ifdef WITH_XSLT_DEBUG_ATTRIBUTES
541 "updated attribute list %s\n", ncname);
542#endif
543}
544
553static void
555 int depth) {
558 xsltUseAttrSetPtr use = set->useAttrSets;
560
561 while (use != NULL) {
562 /*
563 * Iterate top stylesheet and all imports.
564 */
565 cur = topStyle;
566 while (cur != NULL) {
567 if (cur->attributeSets) {
568 other = xmlHashLookup2(cur->attributeSets, use->ncname,
569 use->ns);
570 if (other != NULL) {
571 xsltResolveAttrSet(other, topStyle, cur, use->ncname,
572 use->ns, depth + 1);
574 break;
575 }
576 }
578 }
579
580 next = use->next;
581 /* Free useAttrSets early. */
583 use = next;
584 }
585
586 set->useAttrSets = NULL;
587}
588
599static void
602 const xmlChar *ns, int depth) {
605
606 if (set->state == ATTRSET_RESOLVED)
607 return;
608 if (set->state == ATTRSET_RESOLVING) {
609 xsltTransformError(NULL, topStyle, NULL,
610 "xsl:attribute-set : use-attribute-sets recursion detected"
611 " on %s\n", name);
612 topStyle->errors++;
613 set->state = ATTRSET_RESOLVED;
614 return;
615 }
616 if (depth > 100) {
617 xsltTransformError(NULL, topStyle, NULL,
618 "xsl:attribute-set : use-attribute-sets maximum recursion "
619 "depth exceeded on %s\n", name);
620 topStyle->errors++;
621 return;
622 }
623
624 set->state = ATTRSET_RESOLVING;
625
626 xsltResolveUseAttrSets(set, topStyle, depth);
627
628 /* Merge imported sets. */
630 while (cur != NULL) {
631 if (cur->attributeSets != NULL) {
632 other = xmlHashLookup2(cur->attributeSets, name, ns);
633
634 if (other != NULL) {
635#ifdef WITH_XSLT_DEBUG_ATTRIBUTES
637 "xsl:attribute-set : merging import for %s\n", name);
638#endif
641 xmlHashRemoveEntry2(cur->attributeSets, name, ns, NULL);
643 }
644 }
645
647 }
648
649 set->state = ATTRSET_RESOLVED;
650}
651
661static void
662xsltResolveSASCallback(void *payload, void *data,
663 const xmlChar *name, const xmlChar *ns,
667 xsltStylesheetPtr topStyle = asctx->topStyle;
669
670 if (asctx->error) {
671 if (style != topStyle)
673 return;
674 }
675
676 xsltResolveAttrSet(set, topStyle, style, name, ns, 1);
677
678 /* Move attribute sets to top stylesheet. */
679 if (style != topStyle) {
680 /*
681 * This imported stylesheet won't be visited anymore. Don't bother
682 * removing the hash entry.
683 */
684 if (xmlHashAddEntry2(topStyle->attributeSets, name, ns, set) < 0) {
686 "xsl:attribute-set : internal error, can't move imported "
687 " attribute set %s\n", name);
688 asctx->error = 1;
690 }
691 }
692}
693
700void
703 xsltAttrSetContext asctx;
704
705#ifdef WITH_XSLT_DEBUG_ATTRIBUTES
707 "Resolving attribute sets references\n");
708#endif
709 asctx.topStyle = style;
710 asctx.error = 0;
711 cur = style;
712 while (cur != NULL) {
713 if (cur->attributeSets != NULL) {
714 if (style->attributeSets == NULL) {
715#ifdef WITH_XSLT_DEBUG_ATTRIBUTES
717 "creating attribute set table\n");
718#endif
719 style->attributeSets = xmlHashCreate(10);
720 }
721 asctx.style = cur;
723 &asctx);
724
725 if (cur != style) {
726 /*
727 * the attribute lists have either been migrated to style
728 * or freed directly in xsltResolveSASCallback()
729 */
730 xmlHashFree(cur->attributeSets, NULL);
731 cur->attributeSets = NULL;
732 }
733 }
735 }
736}
737
747void
749 xmlNodePtr contextNode,
750 xmlNodePtr inst,
751 xsltElemPreCompPtr castedComp)
752{
753#ifdef XSLT_REFACTORED
754 xsltStyleItemAttributePtr comp =
755 (xsltStyleItemAttributePtr) castedComp;
756#else
757 xsltStylePreCompPtr comp = (xsltStylePreCompPtr) castedComp;
758#endif
759 xmlNodePtr targetElem;
760 xmlChar *prop = NULL;
761 const xmlChar *name = NULL, *prefix = NULL, *nsName = NULL;
762 xmlChar *value = NULL;
763 xmlNsPtr ns = NULL;
764 xmlAttrPtr attr;
765
766 if ((ctxt == NULL) || (contextNode == NULL) || (inst == NULL) ||
767 (inst->type != XML_ELEMENT_NODE) )
768 return;
769
770 /*
771 * A comp->has_name == 0 indicates that we need to skip this instruction,
772 * since it was evaluated to be invalid already during compilation.
773 */
774 if (!comp->has_name)
775 return;
776 /*
777 * BIG NOTE: This previously used xsltGetSpecialNamespace() and
778 * xsltGetNamespace(), but since both are not appropriate, we
779 * will process namespace lookup here to avoid adding yet another
780 * ns-lookup function to namespaces.c.
781 */
782 /*
783 * SPEC XSLT 1.0: Error cases:
784 * - Creating nodes other than text nodes during the instantiation of
785 * the content of the xsl:attribute element; implementations may
786 * either signal the error or ignore the offending nodes."
787 */
788
789 if (comp == NULL) {
790 xsltTransformError(ctxt, NULL, inst,
791 "Internal error in xsltAttribute(): "
792 "The XSLT 'attribute' instruction was not compiled.\n");
793 return;
794 }
795 /*
796 * TODO: Shouldn't ctxt->insert == NULL be treated as an internal error?
797 * So report an internal error?
798 */
799 if (ctxt->insert == NULL)
800 return;
801 /*
802 * SPEC XSLT 1.0:
803 * "Adding an attribute to a node that is not an element;
804 * implementations may either signal the error or ignore the attribute."
805 *
806 * TODO: I think we should signal such errors in the future, and maybe
807 * provide an option to ignore such errors.
808 */
809 targetElem = ctxt->insert;
810 if (targetElem->type != XML_ELEMENT_NODE)
811 return;
812
813 /*
814 * SPEC XSLT 1.0:
815 * "Adding an attribute to an element after children have been added
816 * to it; implementations may either signal the error or ignore the
817 * attribute."
818 *
819 * TODO: We should decide whether not to report such errors or
820 * to ignore them; note that we *ignore* if the parent is not an
821 * element, but here we report an error.
822 */
823 if (targetElem->children != NULL) {
824 /*
825 * NOTE: Ah! This seems to be intended to support streamed
826 * result generation!.
827 */
828 xsltTransformError(ctxt, NULL, inst,
829 "xsl:attribute: Cannot add attributes to an "
830 "element if children have been already added "
831 "to the element.\n");
832 return;
833 }
834
835 /*
836 * Process the name
837 * ----------------
838 */
839
840#ifdef WITH_DEBUGGER
841 if (ctxt->debugStatus != XSLT_DEBUG_NONE)
842 xslHandleDebugger(inst, contextNode, NULL, ctxt);
843#endif
844
845 if (comp->name == NULL) {
846 /* TODO: fix attr acquisition wrt to the XSLT namespace */
847 prop = xsltEvalAttrValueTemplate(ctxt, inst,
848 (const xmlChar *) "name", XSLT_NAMESPACE);
849 if (prop == NULL) {
850 xsltTransformError(ctxt, NULL, inst,
851 "xsl:attribute: The attribute 'name' is missing.\n");
852 goto error;
853 }
854 if (xmlValidateQName(prop, 0)) {
855 xsltTransformError(ctxt, NULL, inst,
856 "xsl:attribute: The effective name '%s' is not a "
857 "valid QName.\n", prop);
858 /* we fall through to catch any further errors, if possible */
859 }
860
861 /*
862 * Reject a name of "xmlns".
863 */
864 if (xmlStrEqual(prop, BAD_CAST "xmlns")) {
865 xsltTransformError(ctxt, NULL, inst,
866 "xsl:attribute: The effective name 'xmlns' is not allowed.\n");
867 xmlFree(prop);
868 goto error;
869 }
870
871 name = xsltSplitQName(ctxt->dict, prop, &prefix);
872 xmlFree(prop);
873 } else {
874 /*
875 * The "name" value was static.
876 */
877#ifdef XSLT_REFACTORED
878 prefix = comp->nsPrefix;
879 name = comp->name;
880#else
881 name = xsltSplitQName(ctxt->dict, comp->name, &prefix);
882#endif
883 }
884
885 /*
886 * Process namespace semantics
887 * ---------------------------
888 *
889 * Evaluate the namespace name.
890 */
891 if (comp->has_ns) {
892 /*
893 * The "namespace" attribute was existent.
894 */
895 if (comp->ns != NULL) {
896 /*
897 * No AVT; just plain text for the namespace name.
898 */
899 if (comp->ns[0] != 0)
900 nsName = comp->ns;
901 } else {
902 xmlChar *tmpNsName;
903 /*
904 * Eval the AVT.
905 */
906 /* TODO: check attr acquisition wrt to the XSLT namespace */
907 tmpNsName = xsltEvalAttrValueTemplate(ctxt, inst,
908 (const xmlChar *) "namespace", XSLT_NAMESPACE);
909 /*
910 * This fixes bug #302020: The AVT might also evaluate to the
911 * empty string; this means that the empty string also indicates
912 * "no namespace".
913 * SPEC XSLT 1.0:
914 * "If the string is empty, then the expanded-name of the
915 * attribute has a null namespace URI."
916 */
917 if ((tmpNsName != NULL) && (tmpNsName[0] != 0))
918 nsName = xmlDictLookup(ctxt->dict, BAD_CAST tmpNsName, -1);
919 xmlFree(tmpNsName);
920 }
921
922 if (xmlStrEqual(nsName, BAD_CAST "http://www.w3.org/2000/xmlns/")) {
923 xsltTransformError(ctxt, NULL, inst,
924 "xsl:attribute: Namespace http://www.w3.org/2000/xmlns/ "
925 "forbidden.\n");
926 goto error;
927 }
928 if (xmlStrEqual(nsName, XML_XML_NAMESPACE)) {
929 prefix = BAD_CAST "xml";
930 } else if (xmlStrEqual(prefix, BAD_CAST "xml")) {
931 prefix = NULL;
932 }
933 } else if (prefix != NULL) {
934 /*
935 * SPEC XSLT 1.0:
936 * "If the namespace attribute is not present, then the QName is
937 * expanded into an expanded-name using the namespace declarations
938 * in effect for the xsl:attribute element, *not* including any
939 * default namespace declaration."
940 */
941 ns = xmlSearchNs(inst->doc, inst, prefix);
942 if (ns == NULL) {
943 /*
944 * Note that this is treated as an error now (checked with
945 * Saxon, Xalan-J and MSXML).
946 */
947 xsltTransformError(ctxt, NULL, inst,
948 "xsl:attribute: The QName '%s:%s' has no "
949 "namespace binding in scope in the stylesheet; "
950 "this is an error, since the namespace was not "
951 "specified by the instruction itself.\n", prefix, name);
952 } else
953 nsName = ns->href;
954 }
955
956 /*
957 * Find/create a matching ns-decl in the result tree.
958 */
959 ns = NULL;
960
961#if 0
962 if (0) {
963 /*
964 * OPTIMIZE TODO: How do we know if we are adding to a
965 * fragment or to the result tree?
966 *
967 * If we are adding to a result tree fragment (i.e., not to the
968 * actual result tree), we'll don't bother searching for the
969 * ns-decl, but just store it in the dummy-doc of the result
970 * tree fragment.
971 */
972 if (nsName != NULL) {
973 /*
974 * TODO: Get the doc of @targetElem.
975 */
976 ns = xsltTreeAcquireStoredNs(some doc, nsName, prefix);
977 }
978 }
979#endif
980
981 if (nsName != NULL) {
982 /*
983 * Something about ns-prefixes:
984 * SPEC XSLT 1.0:
985 * "XSLT processors may make use of the prefix of the QName specified
986 * in the name attribute when selecting the prefix used for outputting
987 * the created attribute as XML; however, they are not required to do
988 * so and, if the prefix is xmlns, they must not do so"
989 */
990 /*
991 * xsl:attribute can produce a scenario where the prefix is NULL,
992 * so generate a prefix.
993 */
994 if ((prefix == NULL) || xmlStrEqual(prefix, BAD_CAST "xmlns")) {
995 xmlChar *pref = xmlStrdup(BAD_CAST "ns_1");
996
997 ns = xsltGetSpecialNamespace(ctxt, inst, nsName, pref, targetElem);
998
999 xmlFree(pref);
1000 } else {
1001 ns = xsltGetSpecialNamespace(ctxt, inst, nsName, prefix,
1002 targetElem);
1003 }
1004 if (ns == NULL) {
1005 xsltTransformError(ctxt, NULL, inst,
1006 "Namespace fixup error: Failed to acquire an in-scope "
1007 "namespace binding for the generated attribute '{%s}%s'.\n",
1008 nsName, name);
1009 goto error;
1010 }
1011 }
1012 /*
1013 * Construction of the value
1014 * -------------------------
1015 */
1016 if (inst->children == NULL) {
1017 /*
1018 * No content.
1019 * TODO: Do we need to put the empty string in ?
1020 */
1021 attr = xmlSetNsProp(ctxt->insert, ns, name, (const xmlChar *) "");
1022 } else if ((inst->children->next == NULL) &&
1023 ((inst->children->type == XML_TEXT_NODE) ||
1024 (inst->children->type == XML_CDATA_SECTION_NODE)))
1025 {
1026 xmlNodePtr copyTxt;
1027
1028 /*
1029 * xmlSetNsProp() will take care of duplicates.
1030 */
1031 attr = xmlSetNsProp(ctxt->insert, ns, name, NULL);
1032 if (attr == NULL) /* TODO: report error ? */
1033 goto error;
1034 /*
1035 * This was taken over from xsltCopyText() (transform.c).
1036 */
1037 if (ctxt->internalized &&
1038 (ctxt->insert->doc != NULL) &&
1039 (ctxt->insert->doc->dict == ctxt->dict))
1040 {
1041 copyTxt = xmlNewText(NULL);
1042 if (copyTxt == NULL) /* TODO: report error */
1043 goto error;
1044 /*
1045 * This is a safe scenario where we don't need to lookup
1046 * the dict.
1047 */
1048 copyTxt->content = inst->children->content;
1049 /*
1050 * Copy "disable-output-escaping" information.
1051 * TODO: Does this have any effect for attribute values
1052 * anyway?
1053 */
1054 if (inst->children->name == xmlStringTextNoenc)
1055 copyTxt->name = xmlStringTextNoenc;
1056 } else {
1057 /*
1058 * Copy the value.
1059 */
1060 copyTxt = xmlNewText(inst->children->content);
1061 if (copyTxt == NULL) /* TODO: report error */
1062 goto error;
1063 }
1064 attr->children = attr->last = copyTxt;
1065 copyTxt->parent = (xmlNodePtr) attr;
1066 copyTxt->doc = attr->doc;
1067 /*
1068 * Copy "disable-output-escaping" information.
1069 * TODO: Does this have any effect for attribute values
1070 * anyway?
1071 */
1072 if (inst->children->name == xmlStringTextNoenc)
1073 copyTxt->name = xmlStringTextNoenc;
1074
1075 /*
1076 * since we create the attribute without content IDness must be
1077 * asserted as a second step
1078 */
1079 if ((copyTxt->content != NULL) &&
1080 (xmlIsID(attr->doc, attr->parent, attr)))
1081 xmlAddID(NULL, attr->doc, copyTxt->content, attr);
1082 } else {
1083 /*
1084 * The sequence constructor might be complex, so instantiate it.
1085 */
1086 value = xsltEvalTemplateString(ctxt, contextNode, inst);
1087 if (value != NULL) {
1088 attr = xmlSetNsProp(ctxt->insert, ns, name, value);
1089 xmlFree(value);
1090 } else {
1091 /*
1092 * TODO: Do we have to add the empty string to the attr?
1093 * TODO: Does a value of NULL indicate an
1094 * error in xsltEvalTemplateString() ?
1095 */
1096 attr = xmlSetNsProp(ctxt->insert, ns, name,
1097 (const xmlChar *) "");
1098 }
1099 }
1100
1101error:
1102 return;
1103}
1104
1117void
1119 xmlNodePtr inst,
1120 const xmlChar *attrSets)
1121{
1122 const xmlChar *ncname = NULL;
1123 const xmlChar *prefix = NULL;
1124 const xmlChar *curstr, *endstr;
1127
1128 if (attrSets == NULL) {
1129 if (inst == NULL)
1130 return;
1131 else {
1132 /*
1133 * Extract the value from @inst.
1134 */
1135 if (inst->type == XML_ATTRIBUTE_NODE) {
1136 if ( ((xmlAttrPtr) inst)->children != NULL)
1137 attrSets = ((xmlAttrPtr) inst)->children->content;
1138
1139 }
1140 if (attrSets == NULL) {
1141 /*
1142 * TODO: Return an error?
1143 */
1144 return;
1145 }
1146 }
1147 }
1148 /*
1149 * Parse/apply the list of QNames.
1150 */
1151 curstr = attrSets;
1152 while (*curstr != 0) {
1153 while (IS_BLANK(*curstr))
1154 curstr++;
1155 if (*curstr == 0)
1156 break;
1157 endstr = curstr;
1158 while ((*endstr != 0) && (!IS_BLANK(*endstr)))
1159 endstr++;
1160 curstr = xmlDictLookup(ctxt->dict, curstr, endstr - curstr);
1161 if (curstr) {
1162 xmlNsPtr ns;
1163 const xmlChar *nsUri = NULL;
1164
1165#ifdef WITH_XSLT_DEBUG_ATTRIBUTES
1167 "apply attribute set %s\n", curstr);
1168#endif
1169
1170 if (xmlValidateQName(curstr, 0)) {
1171 xsltTransformError(ctxt, NULL, inst,
1172 "The name '%s' in use-attribute-sets is not a valid "
1173 "QName.\n", curstr);
1174 return;
1175 }
1176
1177 ncname = xsltSplitQName(ctxt->dict, curstr, &prefix);
1178 if (prefix != NULL) {
1179 ns = xmlSearchNs(inst->doc, inst, prefix);
1180 if (ns == NULL) {
1181 xsltTransformError(ctxt, NULL, inst,
1182 "use-attribute-set : No namespace found for QName "
1183 "'%s:%s'\n", prefix, ncname);
1184 return;
1185 }
1186 nsUri = ns->href;
1187 }
1188
1189 style = ctxt->style;
1190
1191#ifdef WITH_DEBUGGER
1192 if ((style != NULL) &&
1193 (style->attributeSets != NULL) &&
1194 (ctxt->debugStatus != XSLT_DEBUG_NONE))
1195 {
1196 set = xmlHashLookup2(style->attributeSets, ncname, nsUri);
1197 if ((set != NULL) && (set->attrs != NULL) &&
1198 (set->attrs->attr != NULL))
1199 xslHandleDebugger(set->attrs->attr->parent, node, NULL,
1200 ctxt);
1201 }
1202#endif
1203 /*
1204 * Lookup the referenced attribute-set. All attribute sets were
1205 * moved to the top stylesheet so there's no need to iterate
1206 * imported stylesheets
1207 */
1208 set = xmlHashLookup2(style->attributeSets, ncname, nsUri);
1209 if (set != NULL) {
1210 xsltAttrElemPtr cur = set->attrs;
1211 while (cur != NULL) {
1212 if (cur->attr != NULL) {
1213 xsltAttribute(ctxt, node, cur->attr,
1214 cur->attr->psvi);
1215 }
1216 cur = cur->next;
1217 }
1218 }
1219 }
1220 curstr = endstr;
1221 }
1222}
1223
1224static void
1226 const xmlChar *name ATTRIBUTE_UNUSED) {
1228}
1229
1236void
1238 if (style->attributeSets != NULL)
1239 xmlHashFree((xmlHashTablePtr) style->attributeSets,
1241 style->attributeSets = NULL;
1242}
void xsltStylePreCompute(xsltStylesheetPtr style, xmlNodePtr inst)
Definition: preproc.c:2191
Arabic default style
Definition: afstyles.h:94
Definition: list.h:37
struct list * next
Definition: list.h:38
Definition: _set.h:50
#define NULL
Definition: types.h:112
static void xsltFreeAttrElem(xsltAttrElemPtr attr)
Definition: attributes.c:134
static xsltAttrElemPtr xsltAddAttrElemList(xsltAttrElemPtr list, xmlNodePtr attr)
Definition: attributes.c:165
#define ATTRSET_RESOLVING
Definition: attributes.c:52
void xsltResolveStylesheetAttributeSet(xsltStylesheetPtr style)
Definition: attributes.c:701
static void xsltFreeUseAttrSet(xsltUseAttrSetPtr use)
Definition: attributes.c:216
static void xsltFreeAttrElemList(xsltAttrElemPtr list)
Definition: attributes.c:145
xsltAttrSet * xsltAttrSetPtr
Definition: attributes.c:78
static xsltUseAttrSetPtr xsltAddUseAttrSetList(xsltUseAttrSetPtr list, const xmlChar *ncname, const xmlChar *ns)
Definition: attributes.c:248
static void xsltFreeAttrSet(xsltAttrSetPtr set)
Definition: attributes.c:298
void xsltParseStylesheetAttributeSet(xsltStylesheetPtr style, xmlNodePtr cur)
Definition: attributes.c:368
static void xsltFreeAttributeSetsEntry(void *payload, const xmlChar *name ATTRIBUTE_UNUSED)
Definition: attributes.c:1225
static xsltUseAttrSetPtr xsltNewUseAttrSet(const xmlChar *ncname, const xmlChar *ns)
Definition: attributes.c:194
#define ATTRSET_RESOLVED
Definition: attributes.c:53
xsltUseAttrSet * xsltUseAttrSetPtr
Definition: attributes.c:70
void xsltApplyAttributeSet(xsltTransformContextPtr ctxt, xmlNodePtr node, xmlNodePtr inst, const xmlChar *attrSets)
Definition: attributes.c:1118
static void xsltResolveUseAttrSets(xsltAttrSetPtr set, xsltStylesheetPtr topStyle, int depth)
Definition: attributes.c:554
static void xsltResolveSASCallback(void *payload, void *data, const xmlChar *name, const xmlChar *ns, ATTRIBUTE_UNUSED const xmlChar *ignored)
Definition: attributes.c:662
#define IS_BLANK(c)
Definition: attributes.c:45
static void xsltResolveAttrSet(xsltAttrSetPtr set, xsltStylesheetPtr topStyle, xsltStylesheetPtr style, const xmlChar *name, const xmlChar *ns, int depth)
Definition: attributes.c:600
static void xsltFreeUseAttrSetList(xsltUseAttrSetPtr list)
Definition: attributes.c:227
static void xsltMergeAttrSets(xsltAttrSetPtr set, xsltAttrSetPtr other)
Definition: attributes.c:316
void xsltAttribute(xsltTransformContextPtr ctxt, xmlNodePtr contextNode, xmlNodePtr inst, xsltElemPreCompPtr castedComp)
Definition: attributes.c:748
static xsltAttrSetPtr xsltNewAttrSet(void)
Definition: attributes.c:278
static xsltAttrElemPtr xsltNewAttrElem(xmlNodePtr attr)
Definition: attributes.c:113
xsltAttrSetContext * xsltAttrSetContextPtr
Definition: attributes.c:86
void xsltFreeAttributeSetsHashes(xsltStylesheetPtr style)
Definition: attributes.c:1237
xsltAttrElem * xsltAttrElemPtr
Definition: attributes.c:63
uint8_t ignored[3]
Definition: fsck.fat.h:0
FxCollectionEntry * cur
GLint GLint GLsizei GLsizei GLsizei depth
Definition: gl.h:1546
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl.h:1950
#define ATTRIBUTE_UNUSED
Definition: i386-dis.c:36
xsltStylesheetPtr xsltNextImport(xsltStylesheetPtr cur)
Definition: imports.c:297
#define error(str)
Definition: mkdosfs.c:1605
static HWND child
Definition: cursoricon.c:298
int other
Definition: msacm.c:1376
xmlNsPtr xsltGetSpecialNamespace(xsltTransformContextPtr ctxt, xmlNodePtr invocNode, const xmlChar *nsName, const xmlChar *nsPrefix, xmlNodePtr target)
Definition: namespaces.c:319
XMLPUBVAR const xmlChar xmlStringTextNoenc[]
static unsigned __int64 next
Definition: rand_nt.c:6
#define list
Definition: rosglue.h:35
const xmlChar * xmlDictLookup(xmlDictPtr dict, const xmlChar *name, int len)
Definition: dict.c:824
xmlFreeFunc xmlFree
Definition: globals.c:184
xmlMallocFunc xmlMalloc
Definition: globals.c:193
void xmlHashFree(xmlHashTablePtr hash, xmlHashDeallocator dealloc)
Definition: hash.c:229
void * xmlHashLookup2(xmlHashTablePtr hash, const xmlChar *key, const xmlChar *key2)
Definition: hash.c:754
int xmlHashRemoveEntry2(xmlHashTablePtr hash, const xmlChar *key, const xmlChar *key2, xmlHashDeallocator dealloc)
Definition: hash.c:1121
xmlHashTablePtr xmlHashCreate(int size)
Definition: hash.c:160
void xmlHashScanFull(xmlHashTablePtr hash, xmlHashScannerFull scan, void *data)
Definition: hash.c:914
int xmlHashAddEntry2(xmlHashTablePtr hash, const xmlChar *key, const xmlChar *key2, void *payload)
Definition: hash.c:639
#define memset(x, y, z)
Definition: compat.h:39
struct _xsltAttrElem * next
Definition: attributes.c:65
xmlNodePtr attr
Definition: attributes.c:66
xsltStylesheetPtr style
Definition: attributes.c:89
xsltStylesheetPtr topStyle
Definition: attributes.c:88
xsltUseAttrSetPtr useAttrSets
Definition: attributes.c:82
xsltAttrElemPtr attrs
Definition: attributes.c:81
const xmlChar * name
const xmlChar * ns
xmlHashTablePtr attributeSets
xsltStylesheetPtr style
const xmlChar * ncname
Definition: attributes.c:73
const xmlChar * ns
Definition: attributes.c:74
struct _xsltUseAttrSet * next
Definition: attributes.c:72
Definition: cookie.c:202
WCHAR * name
Definition: cookie.c:203
char * name
Definition: compiler.c:66
Definition: name.c:39
WCHAR * name
Definition: name.c:42
Definition: mxnamespace.c:38
xmlChar * xsltEvalAttrValueTemplate(xsltTransformContextPtr ctxt, xmlNodePtr inst, const xmlChar *name, const xmlChar *ns)
Definition: templates.c:410
xmlChar * xsltEvalTemplateString(xsltTransformContextPtr ctxt, xmlNodePtr contextNode, xmlNodePtr inst)
Definition: templates.c:207
Character const *const prefix
Definition: tempnam.cpp:195
XSLTPUBFUN void XSLTCALL xslHandleDebugger(xmlNodePtr cur, xmlNodePtr node, xsltTemplatePtr templ, xsltTransformContextPtr ctxt)
Definition: dlist.c:348
Definition: pdh_main.c:96
XMLPUBFUN xmlIDPtr xmlAddID(xmlValidCtxtPtr ctxt, xmlDocPtr doc, const xmlChar *value, xmlAttrPtr attr)
Definition: valid.c:2517
XMLPUBFUN int xmlIsID(xmlDocPtr doc, xmlNodePtr elem, xmlAttrPtr attr)
Definition: valid.c:2619
#define BAD_CAST
Definition: xmlstring.h:35
XMLPUBFUN int xmlStrEqual(const xmlChar *str1, const xmlChar *str2)
Definition: xmlstring.c:162
unsigned char xmlChar
Definition: xmlstring.h:28
XMLPUBFUN xmlChar * xmlStrdup(const xmlChar *cur)
Definition: xmlstring.c:69
xsltStylePreComp * xsltStylePreCompPtr
void xsltParseTemplateContent(xsltStylesheetPtr style, xmlNodePtr templ)
Definition: xslt.c:4894
#define XSLT_NAMESPACE
Definition: xslt.h:46
void xsltTransformError(xsltTransformContextPtr ctxt, xsltStylesheetPtr style, xmlNodePtr node, const char *msg,...)
Definition: xsltutils.c:762
xmlGenericErrorFunc xsltGenericError
Definition: xsltutils.c:586
xmlGenericErrorFunc xsltGenericDebug
Definition: xsltutils.c:632
void * xsltGenericDebugContext
Definition: xsltutils.c:633
void * xsltGenericErrorContext
Definition: xsltutils.c:587
const xmlChar * xsltSplitQName(xmlDictPtr dict, const xmlChar *name, const xmlChar **prefix)
Definition: xsltutils.c:804
@ XSLT_DEBUG_NONE
Definition: xsltutils.h:304
#define IS_XSLT_NAME(n, val)
Definition: xsltutils.h:60
#define IS_XSLT_ELEM(n)
Definition: xsltutils.h:51