ReactOS 0.4.15-dev-8339-g4028de8
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#include "precomp.h"
13
14#define WITH_XSLT_DEBUG_ATTRIBUTES
15#ifdef WITH_XSLT_DEBUG
16#define WITH_XSLT_DEBUG_ATTRIBUTES
17#endif
18
19/*
20 * Useful macros
21 */
22#ifdef IS_BLANK
23#undef IS_BLANK
24#endif
25
26#define IS_BLANK(c) (((c) == 0x20) || ((c) == 0x09) || ((c) == 0xA) || \
27 ((c) == 0x0D))
28
29#define IS_BLANK_NODE(n) \
30 (((n)->type == XML_TEXT_NODE) && (xsltIsBlank((n)->content)))
31
32#define ATTRSET_UNRESOLVED 0
33#define ATTRSET_RESOLVING 1
34#define ATTRSET_RESOLVED 2
35
36
37/*
38 * The in-memory structure corresponding to an XSLT Attribute in
39 * an attribute set
40 */
41
42
46 struct _xsltAttrElem *next;/* chained list */
47 xmlNodePtr attr; /* the xsl:attribute definition */
48};
49
53 struct _xsltUseAttrSet *next; /* chained list */
55 const xmlChar *ns;
56};
57
61 int state;
62 xsltAttrElemPtr attrs; /* list head */
64};
65
71};
72
73static void
76 const xmlChar *ns, int depth);
77
78/************************************************************************
79 * *
80 * XSLT Attribute handling *
81 * *
82 ************************************************************************/
83
92static xsltAttrElemPtr
95
97 if (cur == NULL) {
99 "xsltNewAttrElem : malloc failed\n");
100 return(NULL);
101 }
102 memset(cur, 0, sizeof(xsltAttrElem));
103 cur->attr = attr;
104 return(cur);
105}
106
113static void
115 xmlFree(attr);
116}
117
124static void
127
128 while (list != NULL) {
129 next = list->next;
131 list = next;
132 }
133}
134
144static xsltAttrElemPtr
147
148 if (attr == NULL)
149 return(list);
150 if (list == NULL)
151 return(xsltNewAttrElem(attr));
152 cur = list;
153 while (cur != NULL) {
154 next = cur->next;
155 if (next == NULL) {
156 cur->next = xsltNewAttrElem(attr);
157 return(list);
158 }
159 cur = next;
160 }
161 return(list);
162}
163
174xsltNewUseAttrSet(const xmlChar *ncname, const xmlChar *ns) {
176
178 if (cur == NULL) {
180 "xsltNewUseAttrSet : malloc failed\n");
181 return(NULL);
182 }
183 memset(cur, 0, sizeof(xsltUseAttrSet));
184 cur->ncname = ncname;
185 cur->ns = ns;
186 return(cur);
187}
188
195static void
197 xmlFree(use);
198}
199
206static void
209
210 while (list != NULL) {
211 next = list->next;
213 list = next;
214 }
215}
216
229 const xmlChar *ns) {
231
232 if (ncname == NULL)
233 return(list);
234 if (list == NULL)
235 return(xsltNewUseAttrSet(ncname, ns));
236 cur = list;
237 while (cur != NULL) {
238 if ((cur->ncname == ncname) && (cur->ns == ns))
239 return(list);
240 next = cur->next;
241 if (next == NULL) {
242 cur->next = xsltNewUseAttrSet(ncname, ns);
243 return(list);
244 }
245 cur = next;
246 }
247 return(list);
248}
249
257static xsltAttrSetPtr
260
262 if (cur == NULL) {
264 "xsltNewAttrSet : malloc failed\n");
265 return(NULL);
266 }
267 memset(cur, 0, sizeof(xsltAttrSet));
268 return(cur);
269}
270
277static void
279 if (set == NULL)
280 return;
281
283 xsltFreeUseAttrSetList(set->useAttrSets);
284 xmlFree(set);
285}
286
295static void
298 xsltAttrElemPtr old = other->attrs;
299 int add;
300
301 while (old != NULL) {
302 /*
303 * Check that the attribute is not yet in the list
304 */
305 cur = set->attrs;
306 add = 1;
307 while (cur != NULL) {
308 xsltStylePreCompPtr curComp = cur->attr->psvi;
309 xsltStylePreCompPtr oldComp = old->attr->psvi;
310
311 if ((curComp->name == oldComp->name) &&
312 (curComp->ns == oldComp->ns)) {
313 add = 0;
314 break;
315 }
316 if (cur->next == NULL)
317 break;
318 cur = cur->next;
319 }
320
321 if (add == 1) {
322 if (cur == NULL) {
323 set->attrs = xsltNewAttrElem(old->attr);
324 } else if (add) {
325 cur->next = xsltNewAttrElem(old->attr);
326 }
327 }
328
329 old = old->next;
330 }
331}
332
333/************************************************************************
334 * *
335 * Module interfaces *
336 * *
337 ************************************************************************/
338
347void
349 const xmlChar *ncname;
350 const xmlChar *prefix;
351 const xmlChar *nsUri = NULL;
352 xmlChar *value;
355
356 if ((cur == NULL) || (style == NULL) || (cur->type != XML_ELEMENT_NODE))
357 return;
358
359 value = xmlGetNsProp(cur, (const xmlChar *)"name", NULL);
360 if ((value == NULL) || (*value == 0)) {
362 "xsl:attribute-set : name is missing\n");
363 if (value)
364 xmlFree(value);
365 return;
366 }
367
368 if (xmlValidateQName(value, 0)) {
370 "xsl:attribute-set : The name '%s' is not a valid QName.\n",
371 value);
372 style->errors++;
373 xmlFree(value);
374 return;
375 }
376
377 ncname = xsltSplitQName(style->dict, value, &prefix);
378 xmlFree(value);
379 value = NULL;
380 if (prefix != NULL) {
381 xmlNsPtr ns = xmlSearchNs(style->doc, cur, prefix);
382 if (ns == NULL) {
384 "xsl:attribute-set : No namespace found for QName '%s:%s'\n",
385 prefix, ncname);
386 style->errors++;
387 return;
388 }
389 nsUri = ns->href;
390 }
391
392 if (style->attributeSets == NULL) {
393#ifdef WITH_XSLT_DEBUG_ATTRIBUTES
395 "creating attribute set table\n");
396#endif
397 style->attributeSets = xmlHashCreate(10);
398 }
399 if (style->attributeSets == NULL)
400 return;
401
402 set = xmlHashLookup2(style->attributeSets, ncname, nsUri);
403 if (set == NULL) {
405 if (set == NULL)
406 return;
407 xmlHashAddEntry2(style->attributeSets, ncname, nsUri, set);
408 }
409
410 /*
411 * Parse the content. Only xsl:attribute elements are allowed.
412 */
413 child = cur->children;
414 while (child != NULL) {
415 /*
416 * Report invalid nodes.
417 */
418 if ((child->type != XML_ELEMENT_NODE) ||
419 (child->ns == NULL) ||
420 (! IS_XSLT_ELEM(child)))
421 {
422 if (child->type == XML_ELEMENT_NODE)
424 "xsl:attribute-set : unexpected child %s\n",
425 child->name);
426 else
428 "xsl:attribute-set : child of unexpected type\n");
429 } else if (!IS_XSLT_NAME(child, "attribute")) {
431 "xsl:attribute-set : unexpected child xsl:%s\n",
432 child->name);
433 } else {
434#ifdef WITH_XSLT_DEBUG_ATTRIBUTES
436 "add attribute to list %s\n", ncname);
437#endif
439 if (child->children != NULL) {
440#ifdef XSLT_REFACTORED
441 xsltParseSequenceConstructor(XSLT_CCTXT(style),
442 child->children);
443#else
445#endif
446 }
447 if (child->psvi == NULL) {
449 "xsl:attribute-set : internal error, attribute %s not "
450 "compiled\n", child->name);
451 }
452 else {
453 set->attrs = xsltAddAttrElemList(set->attrs, child);
454 }
455 }
456
457 child = child->next;
458 }
459
460 /*
461 * Process attribute "use-attribute-sets".
462 */
463 value = xmlGetNsProp(cur, BAD_CAST "use-attribute-sets", NULL);
464 if (value != NULL) {
465 const xmlChar *curval, *endval;
466 curval = value;
467 while (*curval != 0) {
468 while (IS_BLANK(*curval)) curval++;
469 if (*curval == 0)
470 break;
471 endval = curval;
472 while ((*endval != 0) && (!IS_BLANK(*endval))) endval++;
473 curval = xmlDictLookup(style->dict, curval, endval - curval);
474 if (curval) {
475 const xmlChar *ncname2 = NULL;
476 const xmlChar *prefix2 = NULL;
477 const xmlChar *nsUri2 = NULL;
478
479#ifdef WITH_XSLT_DEBUG_ATTRIBUTES
481 "xsl:attribute-set : %s adds use %s\n", ncname, curval);
482#endif
483
484 if (xmlValidateQName(curval, 0)) {
486 "xsl:attribute-set : The name '%s' in "
487 "use-attribute-sets is not a valid QName.\n", curval);
488 style->errors++;
489 xmlFree(value);
490 return;
491 }
492
493 ncname2 = xsltSplitQName(style->dict, curval, &prefix2);
494 if (prefix2 != NULL) {
495 xmlNsPtr ns2 = xmlSearchNs(style->doc, cur, prefix2);
496 if (ns2 == NULL) {
498 "xsl:attribute-set : No namespace found for QName "
499 "'%s:%s' in use-attribute-sets\n",
500 prefix2, ncname2);
501 style->errors++;
502 xmlFree(value);
503 return;
504 }
505 nsUri2 = ns2->href;
506 }
507 set->useAttrSets = xsltAddUseAttrSetList(set->useAttrSets,
508 ncname2, nsUri2);
509 }
510 curval = endval;
511 }
512 xmlFree(value);
513 value = NULL;
514 }
515
516#ifdef WITH_XSLT_DEBUG_ATTRIBUTES
518 "updated attribute list %s\n", ncname);
519#endif
520}
521
530static void
532 int depth) {
535 xsltUseAttrSetPtr use = set->useAttrSets;
537
538 while (use != NULL) {
539 /*
540 * Iterate top stylesheet and all imports.
541 */
542 cur = topStyle;
543 while (cur != NULL) {
544 if (cur->attributeSets) {
545 other = xmlHashLookup2(cur->attributeSets, use->ncname,
546 use->ns);
547 if (other != NULL) {
548 xsltResolveAttrSet(other, topStyle, cur, use->ncname,
549 use->ns, depth + 1);
551 break;
552 }
553 }
555 }
556
557 next = use->next;
558 /* Free useAttrSets early. */
560 use = next;
561 }
562
563 set->useAttrSets = NULL;
564}
565
576static void
579 const xmlChar *ns, int depth) {
582
583 if (set->state == ATTRSET_RESOLVED)
584 return;
585 if (set->state == ATTRSET_RESOLVING) {
586 xsltTransformError(NULL, topStyle, NULL,
587 "xsl:attribute-set : use-attribute-sets recursion detected"
588 " on %s\n", name);
589 topStyle->errors++;
590 set->state = ATTRSET_RESOLVED;
591 return;
592 }
593 if (depth > 100) {
594 xsltTransformError(NULL, topStyle, NULL,
595 "xsl:attribute-set : use-attribute-sets maximum recursion "
596 "depth exceeded on %s\n", name);
597 topStyle->errors++;
598 return;
599 }
600
601 set->state = ATTRSET_RESOLVING;
602
603 xsltResolveUseAttrSets(set, topStyle, depth);
604
605 /* Merge imported sets. */
607 while (cur != NULL) {
608 if (cur->attributeSets != NULL) {
609 other = xmlHashLookup2(cur->attributeSets, name, ns);
610
611 if (other != NULL) {
612#ifdef WITH_XSLT_DEBUG_ATTRIBUTES
614 "xsl:attribute-set : merging import for %s\n", name);
615#endif
618 xmlHashRemoveEntry2(cur->attributeSets, name, ns, NULL);
620 }
621 }
622
624 }
625
626 set->state = ATTRSET_RESOLVED;
627}
628
638static void
639xsltResolveSASCallback(void *payload, void *data,
640 const xmlChar *name, const xmlChar *ns,
644 xsltStylesheetPtr topStyle = asctx->topStyle;
646
647 xsltResolveAttrSet(set, topStyle, style, name, ns, 1);
648
649 /* Move attribute sets to top stylesheet. */
650 if (style != topStyle) {
651 /*
652 * This imported stylesheet won't be visited anymore. Don't bother
653 * removing the hash entry.
654 */
655 if (xmlHashAddEntry2(topStyle->attributeSets, name, ns, set) < 0) {
657 "xsl:attribute-set : internal error, can't move imported "
658 " attribute set %s\n", name);
659 }
660 }
661}
662
669void
672 xsltAttrSetContext asctx;
673
674#ifdef WITH_XSLT_DEBUG_ATTRIBUTES
676 "Resolving attribute sets references\n");
677#endif
678 asctx.topStyle = style;
679 cur = style;
680 while (cur != NULL) {
681 if (cur->attributeSets != NULL) {
682 if (style->attributeSets == NULL) {
683#ifdef WITH_XSLT_DEBUG_ATTRIBUTES
685 "creating attribute set table\n");
686#endif
687 style->attributeSets = xmlHashCreate(10);
688 }
689 asctx.style = cur;
691 &asctx);
692
693 if (cur != style) {
694 /*
695 * the attribute lists have either been migrated to style
696 * or freed directly in xsltResolveSASCallback()
697 */
698 xmlHashFree(cur->attributeSets, NULL);
699 cur->attributeSets = NULL;
700 }
701 }
703 }
704}
705
715void
717 xmlNodePtr contextNode,
718 xmlNodePtr inst,
719 xsltElemPreCompPtr castedComp)
720{
721#ifdef XSLT_REFACTORED
722 xsltStyleItemAttributePtr comp =
723 (xsltStyleItemAttributePtr) castedComp;
724#else
725 xsltStylePreCompPtr comp = (xsltStylePreCompPtr) castedComp;
726#endif
727 xmlNodePtr targetElem;
728 xmlChar *prop = NULL;
729 const xmlChar *name = NULL, *prefix = NULL, *nsName = NULL;
730 xmlChar *value = NULL;
731 xmlNsPtr ns = NULL;
733
734 if ((ctxt == NULL) || (contextNode == NULL) || (inst == NULL) ||
735 (inst->type != XML_ELEMENT_NODE) )
736 return;
737
738 /*
739 * A comp->has_name == 0 indicates that we need to skip this instruction,
740 * since it was evaluated to be invalid already during compilation.
741 */
742 if (!comp->has_name)
743 return;
744 /*
745 * BIG NOTE: This previously used xsltGetSpecialNamespace() and
746 * xsltGetNamespace(), but since both are not appropriate, we
747 * will process namespace lookup here to avoid adding yet another
748 * ns-lookup function to namespaces.c.
749 */
750 /*
751 * SPEC XSLT 1.0: Error cases:
752 * - Creating nodes other than text nodes during the instantiation of
753 * the content of the xsl:attribute element; implementations may
754 * either signal the error or ignore the offending nodes."
755 */
756
757 if (comp == NULL) {
758 xsltTransformError(ctxt, NULL, inst,
759 "Internal error in xsltAttribute(): "
760 "The XSLT 'attribute' instruction was not compiled.\n");
761 return;
762 }
763 /*
764 * TODO: Shouldn't ctxt->insert == NULL be treated as an internal error?
765 * So report an internal error?
766 */
767 if (ctxt->insert == NULL)
768 return;
769 /*
770 * SPEC XSLT 1.0:
771 * "Adding an attribute to a node that is not an element;
772 * implementations may either signal the error or ignore the attribute."
773 *
774 * TODO: I think we should signal such errors in the future, and maybe
775 * provide an option to ignore such errors.
776 */
777 targetElem = ctxt->insert;
778 if (targetElem->type != XML_ELEMENT_NODE)
779 return;
780
781 /*
782 * SPEC XSLT 1.0:
783 * "Adding an attribute to an element after children have been added
784 * to it; implementations may either signal the error or ignore the
785 * attribute."
786 *
787 * TODO: We should decide whether not to report such errors or
788 * to ignore them; note that we *ignore* if the parent is not an
789 * element, but here we report an error.
790 */
791 if (targetElem->children != NULL) {
792 /*
793 * NOTE: Ah! This seems to be intended to support streamed
794 * result generation!.
795 */
796 xsltTransformError(ctxt, NULL, inst,
797 "xsl:attribute: Cannot add attributes to an "
798 "element if children have been already added "
799 "to the element.\n");
800 return;
801 }
802
803 /*
804 * Process the name
805 * ----------------
806 */
807
808#ifdef WITH_DEBUGGER
809 if (ctxt->debugStatus != XSLT_DEBUG_NONE)
810 xslHandleDebugger(inst, contextNode, NULL, ctxt);
811#endif
812
813 if (comp->name == NULL) {
814 /* TODO: fix attr acquisition wrt to the XSLT namespace */
815 prop = xsltEvalAttrValueTemplate(ctxt, inst,
816 (const xmlChar *) "name", XSLT_NAMESPACE);
817 if (prop == NULL) {
818 xsltTransformError(ctxt, NULL, inst,
819 "xsl:attribute: The attribute 'name' is missing.\n");
820 goto error;
821 }
822 if (xmlValidateQName(prop, 0)) {
823 xsltTransformError(ctxt, NULL, inst,
824 "xsl:attribute: The effective name '%s' is not a "
825 "valid QName.\n", prop);
826 /* we fall through to catch any further errors, if possible */
827 }
828
829 /*
830 * Reject a name of "xmlns".
831 */
832 if (xmlStrEqual(prop, BAD_CAST "xmlns")) {
833 xsltTransformError(ctxt, NULL, inst,
834 "xsl:attribute: The effective name 'xmlns' is not allowed.\n");
835 xmlFree(prop);
836 goto error;
837 }
838
839 name = xsltSplitQName(ctxt->dict, prop, &prefix);
840 xmlFree(prop);
841 } else {
842 /*
843 * The "name" value was static.
844 */
845#ifdef XSLT_REFACTORED
846 prefix = comp->nsPrefix;
847 name = comp->name;
848#else
849 name = xsltSplitQName(ctxt->dict, comp->name, &prefix);
850#endif
851 }
852
853 /*
854 * Process namespace semantics
855 * ---------------------------
856 *
857 * Evaluate the namespace name.
858 */
859 if (comp->has_ns) {
860 /*
861 * The "namespace" attribute was existent.
862 */
863 if (comp->ns != NULL) {
864 /*
865 * No AVT; just plain text for the namespace name.
866 */
867 if (comp->ns[0] != 0)
868 nsName = comp->ns;
869 } else {
870 xmlChar *tmpNsName;
871 /*
872 * Eval the AVT.
873 */
874 /* TODO: check attr acquisition wrt to the XSLT namespace */
875 tmpNsName = xsltEvalAttrValueTemplate(ctxt, inst,
876 (const xmlChar *) "namespace", XSLT_NAMESPACE);
877 /*
878 * This fixes bug #302020: The AVT might also evaluate to the
879 * empty string; this means that the empty string also indicates
880 * "no namespace".
881 * SPEC XSLT 1.0:
882 * "If the string is empty, then the expanded-name of the
883 * attribute has a null namespace URI."
884 */
885 if ((tmpNsName != NULL) && (tmpNsName[0] != 0))
886 nsName = xmlDictLookup(ctxt->dict, BAD_CAST tmpNsName, -1);
887 xmlFree(tmpNsName);
888 }
889
890 if (xmlStrEqual(nsName, BAD_CAST "http://www.w3.org/2000/xmlns/")) {
891 xsltTransformError(ctxt, NULL, inst,
892 "xsl:attribute: Namespace http://www.w3.org/2000/xmlns/ "
893 "forbidden.\n");
894 goto error;
895 }
896 if (xmlStrEqual(nsName, XML_XML_NAMESPACE)) {
897 prefix = BAD_CAST "xml";
898 } else if (xmlStrEqual(prefix, BAD_CAST "xml")) {
899 prefix = NULL;
900 }
901 } else if (prefix != NULL) {
902 /*
903 * SPEC XSLT 1.0:
904 * "If the namespace attribute is not present, then the QName is
905 * expanded into an expanded-name using the namespace declarations
906 * in effect for the xsl:attribute element, *not* including any
907 * default namespace declaration."
908 */
909 ns = xmlSearchNs(inst->doc, inst, prefix);
910 if (ns == NULL) {
911 /*
912 * Note that this is treated as an error now (checked with
913 * Saxon, Xalan-J and MSXML).
914 */
915 xsltTransformError(ctxt, NULL, inst,
916 "xsl:attribute: The QName '%s:%s' has no "
917 "namespace binding in scope in the stylesheet; "
918 "this is an error, since the namespace was not "
919 "specified by the instruction itself.\n", prefix, name);
920 } else
921 nsName = ns->href;
922 }
923
924 /*
925 * Find/create a matching ns-decl in the result tree.
926 */
927 ns = NULL;
928
929#if 0
930 if (0) {
931 /*
932 * OPTIMIZE TODO: How do we know if we are adding to a
933 * fragment or to the result tree?
934 *
935 * If we are adding to a result tree fragment (i.e., not to the
936 * actual result tree), we'll don't bother searching for the
937 * ns-decl, but just store it in the dummy-doc of the result
938 * tree fragment.
939 */
940 if (nsName != NULL) {
941 /*
942 * TODO: Get the doc of @targetElem.
943 */
944 ns = xsltTreeAcquireStoredNs(some doc, nsName, prefix);
945 }
946 }
947#endif
948
949 if (nsName != NULL) {
950 /*
951 * Something about ns-prefixes:
952 * SPEC XSLT 1.0:
953 * "XSLT processors may make use of the prefix of the QName specified
954 * in the name attribute when selecting the prefix used for outputting
955 * the created attribute as XML; however, they are not required to do
956 * so and, if the prefix is xmlns, they must not do so"
957 */
958 /*
959 * xsl:attribute can produce a scenario where the prefix is NULL,
960 * so generate a prefix.
961 */
962 if ((prefix == NULL) || xmlStrEqual(prefix, BAD_CAST "xmlns")) {
963 xmlChar *pref = xmlStrdup(BAD_CAST "ns_1");
964
965 ns = xsltGetSpecialNamespace(ctxt, inst, nsName, pref, targetElem);
966
967 xmlFree(pref);
968 } else {
969 ns = xsltGetSpecialNamespace(ctxt, inst, nsName, prefix,
970 targetElem);
971 }
972 if (ns == NULL) {
973 xsltTransformError(ctxt, NULL, inst,
974 "Namespace fixup error: Failed to acquire an in-scope "
975 "namespace binding for the generated attribute '{%s}%s'.\n",
976 nsName, name);
977 goto error;
978 }
979 }
980 /*
981 * Construction of the value
982 * -------------------------
983 */
984 if (inst->children == NULL) {
985 /*
986 * No content.
987 * TODO: Do we need to put the empty string in ?
988 */
989 attr = xmlSetNsProp(ctxt->insert, ns, name, (const xmlChar *) "");
990 } else if ((inst->children->next == NULL) &&
991 ((inst->children->type == XML_TEXT_NODE) ||
992 (inst->children->type == XML_CDATA_SECTION_NODE)))
993 {
994 xmlNodePtr copyTxt;
995
996 /*
997 * xmlSetNsProp() will take care of duplicates.
998 */
999 attr = xmlSetNsProp(ctxt->insert, ns, name, NULL);
1000 if (attr == NULL) /* TODO: report error ? */
1001 goto error;
1002 /*
1003 * This was taken over from xsltCopyText() (transform.c).
1004 */
1005 if (ctxt->internalized &&
1006 (ctxt->insert->doc != NULL) &&
1007 (ctxt->insert->doc->dict == ctxt->dict))
1008 {
1009 copyTxt = xmlNewText(NULL);
1010 if (copyTxt == NULL) /* TODO: report error */
1011 goto error;
1012 /*
1013 * This is a safe scenario where we don't need to lookup
1014 * the dict.
1015 */
1016 copyTxt->content = inst->children->content;
1017 /*
1018 * Copy "disable-output-escaping" information.
1019 * TODO: Does this have any effect for attribute values
1020 * anyway?
1021 */
1022 if (inst->children->name == xmlStringTextNoenc)
1023 copyTxt->name = xmlStringTextNoenc;
1024 } else {
1025 /*
1026 * Copy the value.
1027 */
1028 copyTxt = xmlNewText(inst->children->content);
1029 if (copyTxt == NULL) /* TODO: report error */
1030 goto error;
1031 }
1032 attr->children = attr->last = copyTxt;
1033 copyTxt->parent = (xmlNodePtr) attr;
1034 copyTxt->doc = attr->doc;
1035 /*
1036 * Copy "disable-output-escaping" information.
1037 * TODO: Does this have any effect for attribute values
1038 * anyway?
1039 */
1040 if (inst->children->name == xmlStringTextNoenc)
1041 copyTxt->name = xmlStringTextNoenc;
1042
1043 /*
1044 * since we create the attribute without content IDness must be
1045 * asserted as a second step
1046 */
1047 if ((copyTxt->content != NULL) &&
1048 (xmlIsID(attr->doc, attr->parent, attr)))
1049 xmlAddID(NULL, attr->doc, copyTxt->content, attr);
1050 } else {
1051 /*
1052 * The sequence constructor might be complex, so instantiate it.
1053 */
1054 value = xsltEvalTemplateString(ctxt, contextNode, inst);
1055 if (value != NULL) {
1056 attr = xmlSetNsProp(ctxt->insert, ns, name, value);
1057 xmlFree(value);
1058 } else {
1059 /*
1060 * TODO: Do we have to add the empty string to the attr?
1061 * TODO: Does a value of NULL indicate an
1062 * error in xsltEvalTemplateString() ?
1063 */
1064 attr = xmlSetNsProp(ctxt->insert, ns, name,
1065 (const xmlChar *) "");
1066 }
1067 }
1068
1069error:
1070 return;
1071}
1072
1085void
1087 xmlNodePtr inst,
1088 const xmlChar *attrSets)
1089{
1090 const xmlChar *ncname = NULL;
1091 const xmlChar *prefix = NULL;
1092 const xmlChar *curstr, *endstr;
1095
1096 if (attrSets == NULL) {
1097 if (inst == NULL)
1098 return;
1099 else {
1100 /*
1101 * Extract the value from @inst.
1102 */
1103 if (inst->type == XML_ATTRIBUTE_NODE) {
1104 if ( ((xmlAttrPtr) inst)->children != NULL)
1105 attrSets = ((xmlAttrPtr) inst)->children->content;
1106
1107 }
1108 if (attrSets == NULL) {
1109 /*
1110 * TODO: Return an error?
1111 */
1112 return;
1113 }
1114 }
1115 }
1116 /*
1117 * Parse/apply the list of QNames.
1118 */
1119 curstr = attrSets;
1120 while (*curstr != 0) {
1121 while (IS_BLANK(*curstr))
1122 curstr++;
1123 if (*curstr == 0)
1124 break;
1125 endstr = curstr;
1126 while ((*endstr != 0) && (!IS_BLANK(*endstr)))
1127 endstr++;
1128 curstr = xmlDictLookup(ctxt->dict, curstr, endstr - curstr);
1129 if (curstr) {
1130 xmlNsPtr ns;
1131 const xmlChar *nsUri = NULL;
1132
1133#ifdef WITH_XSLT_DEBUG_ATTRIBUTES
1135 "apply attribute set %s\n", curstr);
1136#endif
1137
1138 if (xmlValidateQName(curstr, 0)) {
1139 xsltTransformError(ctxt, NULL, inst,
1140 "The name '%s' in use-attribute-sets is not a valid "
1141 "QName.\n", curstr);
1142 return;
1143 }
1144
1145 ncname = xsltSplitQName(ctxt->dict, curstr, &prefix);
1146 if (prefix != NULL) {
1147 ns = xmlSearchNs(inst->doc, inst, prefix);
1148 if (ns == NULL) {
1149 xsltTransformError(ctxt, NULL, inst,
1150 "use-attribute-set : No namespace found for QName "
1151 "'%s:%s'\n", prefix, ncname);
1152 return;
1153 }
1154 nsUri = ns->href;
1155 }
1156
1157 style = ctxt->style;
1158
1159#ifdef WITH_DEBUGGER
1160 if ((style != NULL) &&
1161 (style->attributeSets != NULL) &&
1162 (ctxt->debugStatus != XSLT_DEBUG_NONE))
1163 {
1164 set = xmlHashLookup2(style->attributeSets, ncname, nsUri);
1165 if ((set != NULL) && (set->attrs != NULL) &&
1166 (set->attrs->attr != NULL))
1167 xslHandleDebugger(set->attrs->attr->parent, node, NULL,
1168 ctxt);
1169 }
1170#endif
1171 /*
1172 * Lookup the referenced attribute-set. All attribute sets were
1173 * moved to the top stylesheet so there's no need to iterate
1174 * imported stylesheets
1175 */
1176 set = xmlHashLookup2(style->attributeSets, ncname, nsUri);
1177 if (set != NULL) {
1178 xsltAttrElemPtr cur = set->attrs;
1179 while (cur != NULL) {
1180 if (cur->attr != NULL) {
1181 xsltAttribute(ctxt, node, cur->attr,
1182 cur->attr->psvi);
1183 }
1184 cur = cur->next;
1185 }
1186 }
1187 }
1188 curstr = endstr;
1189 }
1190}
1191
1192static void
1194 const xmlChar *name ATTRIBUTE_UNUSED) {
1196}
1197
1204void
1206 if (style->attributeSets != NULL)
1207 xmlHashFree((xmlHashTablePtr) style->attributeSets,
1209 style->attributeSets = NULL;
1210}
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:114
static xsltAttrElemPtr xsltAddAttrElemList(xsltAttrElemPtr list, xmlNodePtr attr)
Definition: attributes.c:145
#define ATTRSET_RESOLVING
Definition: attributes.c:33
void xsltResolveStylesheetAttributeSet(xsltStylesheetPtr style)
Definition: attributes.c:670
static void xsltFreeUseAttrSet(xsltUseAttrSetPtr use)
Definition: attributes.c:196
static void xsltFreeAttrElemList(xsltAttrElemPtr list)
Definition: attributes.c:125
xsltAttrSet * xsltAttrSetPtr
Definition: attributes.c:59
static xsltUseAttrSetPtr xsltAddUseAttrSetList(xsltUseAttrSetPtr list, const xmlChar *ncname, const xmlChar *ns)
Definition: attributes.c:228
static void xsltFreeAttrSet(xsltAttrSetPtr set)
Definition: attributes.c:278
void xsltParseStylesheetAttributeSet(xsltStylesheetPtr style, xmlNodePtr cur)
Definition: attributes.c:348
static void xsltFreeAttributeSetsEntry(void *payload, const xmlChar *name ATTRIBUTE_UNUSED)
Definition: attributes.c:1193
static xsltUseAttrSetPtr xsltNewUseAttrSet(const xmlChar *ncname, const xmlChar *ns)
Definition: attributes.c:174
static xsltAttrSetPtr xsltNewAttrSet()
Definition: attributes.c:258
#define ATTRSET_RESOLVED
Definition: attributes.c:34
xsltUseAttrSet * xsltUseAttrSetPtr
Definition: attributes.c:51
void xsltApplyAttributeSet(xsltTransformContextPtr ctxt, xmlNodePtr node, xmlNodePtr inst, const xmlChar *attrSets)
Definition: attributes.c:1086
static void xsltResolveUseAttrSets(xsltAttrSetPtr set, xsltStylesheetPtr topStyle, int depth)
Definition: attributes.c:531
static void xsltResolveSASCallback(void *payload, void *data, const xmlChar *name, const xmlChar *ns, ATTRIBUTE_UNUSED const xmlChar *ignored)
Definition: attributes.c:639
#define IS_BLANK(c)
Definition: attributes.c:26
static void xsltResolveAttrSet(xsltAttrSetPtr set, xsltStylesheetPtr topStyle, xsltStylesheetPtr style, const xmlChar *name, const xmlChar *ns, int depth)
Definition: attributes.c:577
static void xsltFreeUseAttrSetList(xsltUseAttrSetPtr list)
Definition: attributes.c:207
static void xsltMergeAttrSets(xsltAttrSetPtr set, xsltAttrSetPtr other)
Definition: attributes.c:296
void xsltAttribute(xsltTransformContextPtr ctxt, xmlNodePtr contextNode, xmlNodePtr inst, xsltElemPreCompPtr castedComp)
Definition: attributes.c:716
static xsltAttrElemPtr xsltNewAttrElem(xmlNodePtr attr)
Definition: attributes.c:93
xsltAttrSetContext * xsltAttrSetContextPtr
Definition: attributes.c:67
void xsltFreeAttributeSetsHashes(xsltStylesheetPtr style)
Definition: attributes.c:1205
xsltAttrElem * xsltAttrElemPtr
Definition: attributes.c:44
void xsltStylePreCompute(xsltStylesheetPtr style, xmlNodePtr inst)
Definition: preproc.c:2177
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:251
#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:299
XMLPUBVAR const xmlChar xmlStringTextNoenc[]
static unsigned __int64 next
Definition: rand_nt.c:6
#define list
Definition: rosglue.h:35
XMLPUBFUN const xmlChar *XMLCALL xmlDictLookup(xmlDictPtr dict, const xmlChar *name, int len)
Definition: dict.c:867
XMLPUBVAR xmlMallocFunc xmlMalloc
Definition: globals.h:248
XMLPUBVAR xmlFreeFunc xmlFree
Definition: globals.h:251
XMLPUBFUN int XMLCALL xmlHashAddEntry2(xmlHashTablePtr table, const xmlChar *name, const xmlChar *name2, void *userdata)
Definition: hash.c:406
XMLPUBFUN void XMLCALL xmlHashFree(xmlHashTablePtr table, xmlHashDeallocator f)
Definition: hash.c:322
XMLPUBFUN int XMLCALL xmlHashRemoveEntry2(xmlHashTablePtr table, const xmlChar *name, const xmlChar *name2, xmlHashDeallocator f)
Definition: hash.c:1071
XMLPUBFUN xmlHashTablePtr XMLCALL xmlHashCreate(int size)
Definition: hash.c:176
XMLPUBFUN void XMLCALL xmlHashScanFull(xmlHashTablePtr table, xmlHashScannerFull f, void *data)
Definition: hash.c:875
XMLPUBFUN void *XMLCALL xmlHashLookup2(xmlHashTablePtr table, const xmlChar *name, const xmlChar *name2)
Definition: hash.c:476
XMLPUBFUN xmlNsPtr XMLCALL xmlSearchNs(xmlDocPtr doc, xmlNodePtr node, const xmlChar *nameSpace)
xmlNode * xmlNodePtr
Definition: tree.h:488
XMLPUBFUN xmlChar *XMLCALL xmlGetNsProp(const xmlNode *node, const xmlChar *name, const xmlChar *nameSpace)
XMLPUBFUN xmlNodePtr XMLCALL xmlNewText(const xmlChar *content)
@ XML_ATTRIBUTE_NODE
Definition: tree.h:161
@ XML_CDATA_SECTION_NODE
Definition: tree.h:163
@ XML_TEXT_NODE
Definition: tree.h:162
@ XML_ELEMENT_NODE
Definition: tree.h:160
xmlAttr * xmlAttrPtr
Definition: tree.h:433
#define XML_XML_NAMESPACE
Definition: tree.h:140
#define memset(x, y, z)
Definition: compat.h:39
Definition: tree.h:434
Definition: tree.h:489
xmlChar * content
Definition: tree.h:502
struct _xmlNode * children
Definition: tree.h:493
void * psvi
Definition: tree.h:505
struct _xmlDoc * doc
Definition: tree.h:498
const xmlChar * name
Definition: tree.h:492
xmlElementType type
Definition: tree.h:491
struct _xmlNode * parent
Definition: tree.h:495
Definition: tree.h:389
const xmlChar * href
Definition: tree.h:392
struct _xsltAttrElem * next
Definition: attributes.c:46
xmlNodePtr attr
Definition: attributes.c:47
xsltStylesheetPtr style
Definition: attributes.c:70
xsltStylesheetPtr topStyle
Definition: attributes.c:69
xsltUseAttrSetPtr useAttrSets
Definition: attributes.c:63
xsltAttrElemPtr attrs
Definition: attributes.c:62
const xmlChar * name
const xmlChar * ns
xmlHashTablePtr attributeSets
xsltStylesheetPtr style
const xmlChar * ncname
Definition: attributes.c:54
const xmlChar * ns
Definition: attributes.c:55
struct _xsltUseAttrSet * next
Definition: attributes.c:53
Definition: cookie.c:202
Definition: name.c:39
WCHAR * name
Definition: name.c:42
Definition: mxnamespace.c:45
xmlChar * xsltEvalAttrValueTemplate(xsltTransformContextPtr ctxt, xmlNodePtr inst, const xmlChar *name, const xmlChar *ns)
Definition: templates.c:392
xmlChar * xsltEvalTemplateString(xsltTransformContextPtr ctxt, xmlNodePtr contextNode, xmlNodePtr inst)
Definition: templates.c:189
XSLTPUBFUN void XSLTCALL xslHandleDebugger(xmlNodePtr cur, xmlNodePtr node, xsltTemplatePtr templ, xsltTransformContextPtr ctxt)
Definition: dlist.c:348
Definition: pdh_main.c:94
XMLPUBFUN xmlIDPtr XMLCALL xmlAddID(xmlValidCtxtPtr ctxt, xmlDocPtr doc, const xmlChar *value, xmlAttrPtr attr)
Definition: valid.c:2672
XMLPUBFUN int XMLCALL xmlIsID(xmlDocPtr doc, xmlNodePtr elem, xmlAttrPtr attr)
Definition: valid.c:2774
XMLPUBFUN xmlChar *XMLCALL xmlStrdup(const xmlChar *cur)
Definition: xmlstring.c:67
#define BAD_CAST
Definition: xmlstring.h:35
XMLPUBFUN int XMLCALL xmlStrEqual(const xmlChar *str1, const xmlChar *str2)
Definition: xmlstring.c:160
unsigned char xmlChar
Definition: xmlstring.h:28
xsltStylePreComp * xsltStylePreCompPtr
void xsltParseTemplateContent(xsltStylesheetPtr style, xmlNodePtr templ)
Definition: xslt.c:4878
#define XSLT_NAMESPACE
Definition: xslt.h:46
void xsltTransformError(xsltTransformContextPtr ctxt, xsltStylesheetPtr style, xmlNodePtr node, const char *msg,...)
Definition: xsltutils.c:678
xmlGenericErrorFunc xsltGenericError
Definition: xsltutils.c:502
xmlGenericErrorFunc xsltGenericDebug
Definition: xsltutils.c:548
void * xsltGenericDebugContext
Definition: xsltutils.c:549
void * xsltGenericErrorContext
Definition: xsltutils.c:503
const xmlChar * xsltSplitQName(xmlDictPtr dict, const xmlChar *name, const xmlChar **prefix)
Definition: xsltutils.c:720
@ XSLT_DEBUG_NONE
Definition: xsltutils.h:273
#define IS_XSLT_NAME(n, val)
Definition: xsltutils.h:60
#define IS_XSLT_ELEM(n)
Definition: xsltutils.h:51